summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp11
-rw-r--r--Android.mk2
-rw-r--r--api/current.txt17
-rw-r--r--api/removed.txt2
-rw-r--r--api/system-current.txt25
-rw-r--r--api/test-current.txt13
-rw-r--r--cmds/statsd/Android.bp2
-rw-r--r--cmds/statsd/src/StatsService.cpp54
-rw-r--r--cmds/statsd/src/StatsService.h8
-rw-r--r--cmds/statsd/src/atoms.proto20
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp7
-rw-r--r--cmds/statsd/src/external/TrainInfoPuller.cpp53
-rw-r--r--cmds/statsd/src/external/TrainInfoPuller.h38
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.cpp7
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h10
-rw-r--r--cmds/statsd/src/logd/LogEvent.cpp31
-rw-r--r--cmds/statsd/src/logd/LogEvent.h13
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp7
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h1
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp10
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp6
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h4
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp18
-rw-r--r--cmds/statsd/src/stats_log.proto1
-rw-r--r--cmds/statsd/src/stats_log_util.cpp7
-rw-r--r--cmds/statsd/src/stats_log_util.h2
-rw-r--r--cmds/statsd/src/storage/StorageManager.cpp68
-rw-r--r--cmds/statsd/src/storage/StorageManager.h17
-rw-r--r--cmds/statsd/statsd.rc1
-rw-r--r--cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp46
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp16
-rw-r--r--cmds/statsd/tests/storage/StorageManager_test.cpp52
-rw-r--r--config/hiddenapi-greylist.txt3
-rw-r--r--core/java/android/app/ContextImpl.java21
-rw-r--r--core/java/android/app/SystemServiceRegistry.java8
-rw-r--r--core/java/android/content/Intent.java29
-rw-r--r--core/java/android/content/pm/PackageManager.java17
-rw-r--r--core/java/android/content/pm/PackageParser.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java13
-rw-r--r--core/java/android/net/InterfaceConfiguration.java5
-rw-r--r--core/java/android/net/NetworkCapabilities.java14
-rw-r--r--core/java/android/net/NetworkPolicyManager.java10
-rw-r--r--core/java/android/os/GraphicsEnvironment.java50
-rw-r--r--core/java/android/os/IStatsManager.aidl21
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/provider/Settings.java24
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillCallback.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillController.java4
-rw-r--r--core/java/android/service/autofill/augmented/FillRequest.java2
-rw-r--r--core/java/android/service/autofill/augmented/FillResponse.java4
-rw-r--r--core/java/android/service/autofill/augmented/FillWindow.java4
-rw-r--r--core/java/android/service/autofill/augmented/PresentationParams.java122
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java6
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java7
-rw-r--r--core/java/android/util/StatsLog.java95
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java14
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/autofill/AutofillManager.java6
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java30
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java35
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java41
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java17
-rw-r--r--core/java/android/webkit/WebView.java11
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp83
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp2
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp2
-rw-r--r--core/jni/android/graphics/Graphics.cpp127
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h8
-rw-r--r--core/jni/android/graphics/ImageDecoder.cpp4
-rw-r--r--core/proto/android/server/connectivity/Android.bp25
-rw-r--r--core/res/res/drawable/ic_qs_night_display_on.xml23
-rw-r--r--core/res/res/values/config.xml7
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java41
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java5
-rw-r--r--graphics/java/android/graphics/Bitmap.java138
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java9
-rw-r--r--graphics/java/android/graphics/ColorSpace.java2
-rw-r--r--graphics/java/android/graphics/ImageDecoder.java9
-rw-r--r--libs/hwui/Readback.cpp2
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp5
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp26
-rw-r--r--libs/hwui/renderthread/RenderThread.h3
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp69
-rw-r--r--libs/hwui/renderthread/VulkanManager.h23
-rw-r--r--libs/hwui/tests/common/TestUtils.cpp2
-rw-r--r--libs/input/PointerController.cpp124
-rw-r--r--libs/input/PointerController.h14
-rw-r--r--location/java/android/location/LocationRequest.java29
-rw-r--r--location/java/com/android/internal/location/ProviderRequest.java11
-rw-r--r--location/lib/api/current.txt3
-rw-r--r--location/lib/java/com/android/location/provider/LocationRequestUnbundled.java9
-rw-r--r--location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java6
-rw-r--r--media/apex/java/android/media/MediaController2.java2
-rw-r--r--media/java/android/media/MediaPlayer.java21
-rw-r--r--media/java/android/media/session/ControllerLink.java27
-rw-r--r--media/java/android/media/session/ISessionCallback.aidl2
-rw-r--r--media/java/android/media/session/ISessionController.aidl1
-rw-r--r--media/java/android/media/session/MediaController.java13
-rw-r--r--media/java/android/media/session/MediaSession.java13
-rw-r--r--media/java/android/media/session/MediaSessionEngine.java27
-rw-r--r--media/java/android/media/session/SessionCallbackLink.java36
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java1
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java1
-rw-r--r--packages/NetworkStack/AndroidManifest.xml1
-rw-r--r--packages/NetworkStack/src/android/net/ip/IpClient.java10
-rw-r--r--packages/NetworkStack/src/com/android/server/NetworkStackService.java3
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java63
-rw-r--r--packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java2
-rw-r--r--packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml2
-rw-r--r--packages/SettingsLib/res/drawable/ic_info_outline_24.xml27
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java2
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml21
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml13
-rw-r--r--packages/SystemUI/res/drawable/ic_signal_airplane.xml22
-rw-r--r--packages/SystemUI/res/layout-land/global_actions_grid.xml80
-rw-r--r--packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml82
-rw-r--r--packages/SystemUI/res/layout/global_actions_grid.xml17
-rw-r--r--packages/SystemUI/res/layout/global_actions_grid_item.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/DependencyBinder.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/MultiListLayout.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt27
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java3
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java2
-rw-r--r--services/core/java/com/android/server/ExtconUEventObserver.java13
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java5
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java38
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java113
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/BroadcastDispatcher.java76
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java19
-rw-r--r--services/core/java/com/android/server/appbinding/AppBindingService.java38
-rw-r--r--services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java37
-rw-r--r--services/core/java/com/android/server/gpu/GpuService.java101
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java16
-rw-r--r--services/core/java/com/android/server/net/LockdownVpnTracker.java8
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java11
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java2
-rw-r--r--services/core/java/com/android/server/power/AttentionDetector.java5
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java39
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java39
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java22
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java19
-rw-r--r--services/net/Android.bp3
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java2
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java13
-rw-r--r--telephony/java/android/telephony/LocationAccessPolicy.java294
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationState.java20
-rw-r--r--telephony/java/android/telephony/ServiceState.java26
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java2
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java45
-rw-r--r--telephony/java/android/telephony/TelephonyScanManager.java13
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java31
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl5
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java6
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java33
188 files changed, 2790 insertions, 1163 deletions
diff --git a/Android.bp b/Android.bp
index 183121b3cf67..995fe3e2465e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -773,7 +773,7 @@ java_defaults {
"android.hardware.vibrator-V1.3-java",
"android.hardware.wifi-V1.0-java-constants",
"networkstack-aidl-interfaces-java",
- "netd_aidl_interface-java",
+ "netd_aidl_parcelables-java",
"devicepolicyprotosnano",
],
@@ -1187,6 +1187,15 @@ packages_to_document = [
"org/apache/http/params",
]
+// Make the api/current.txt file available for use by modules in other
+// directories.
+filegroup {
+ name: "frameworks-base-api-current.txt",
+ srcs: [
+ "api/current.txt",
+ ],
+}
+
framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
"-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
"-overview $(location core/java/overview.html) " +
diff --git a/Android.mk b/Android.mk
index 9a91dd1c491a..c58f7af1d7d5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -77,8 +77,6 @@ docs offline-sdk-docs: $(OUT_DOCS)/offline-sdk-timestamp
# Run this for checkbuild
checkbuild: doc-comment-check-docs
-# Check comment when you are updating the API
-update-api: doc-comment-check-docs
# ==== hiddenapi lists =======================================
ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
diff --git a/api/current.txt b/api/current.txt
index 2206971e40dc..747a3f5d7c53 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27445,6 +27445,7 @@ package android.media.session {
method public void seekTo(long);
method public void sendCustomAction(@NonNull android.media.session.PlaybackState.CustomAction, @Nullable android.os.Bundle);
method public void sendCustomAction(@NonNull String, @Nullable android.os.Bundle);
+ method public void setPlaybackSpeed(float);
method public void setRating(android.media.Rating);
method public void skipToNext();
method public void skipToPrevious();
@@ -27495,6 +27496,7 @@ package android.media.session {
method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
method public void onRewind();
method public void onSeekTo(long);
+ method public void onSetPlaybackSpeed(float);
method public void onSetRating(@NonNull android.media.Rating);
method public void onSkipToNext();
method public void onSkipToPrevious();
@@ -35050,7 +35052,7 @@ package android.os {
method public android.os.PowerManager.WakeLock newWakeLock(int, String);
method public void reboot(String);
method public void registerThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback, @NonNull java.util.concurrent.Executor);
- method public void unregisterThermalStatusCallback(android.os.PowerManager.ThermalStatusCallback);
+ method public void unregisterThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
@@ -45070,12 +45072,12 @@ package android.telephony {
method public boolean canChangeDtmfToneLength();
method @Nullable public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
method public android.telephony.TelephonyManager createForSubscriptionId(int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
method public int getCardIdForDefaultEuicc();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
method public int getCarrierIdFromSimMccMnc();
- method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.CellLocation getCellLocation();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.telephony.CellLocation getCellLocation();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getCurrentEmergencyNumberList();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getCurrentEmergencyNumberList(int);
method public int getDataActivity();
@@ -45105,7 +45107,7 @@ package android.telephony {
method public int getPhoneCount();
method public int getPhoneType();
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.ServiceState getServiceState();
+ method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
method @Nullable public android.telephony.SignalStrength getSignalStrength();
method public int getSimCarrierId();
method @Nullable public CharSequence getSimCarrierIdName();
@@ -45147,8 +45149,8 @@ package android.telephony {
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
method public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
@@ -48999,6 +49001,7 @@ package android.util {
}
public final class StatsLog {
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public static boolean logBinaryPushStateChanged(@NonNull String, long, int, int, @NonNull long[]);
method public static boolean logEvent(int);
method public static boolean logStart(int);
method public static boolean logStop(int);
@@ -53473,6 +53476,7 @@ package android.view.contentcapture {
method public void close();
method @NonNull public final android.view.contentcapture.ContentCaptureSession createContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext);
method public final void destroy();
+ method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
method 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 newVirtualViewStructure(@NonNull android.view.autofill.AutofillId, long);
@@ -53480,6 +53484,7 @@ package android.view.contentcapture {
method public final void notifyViewDisappeared(@NonNull android.view.autofill.AutofillId);
method public final void notifyViewTextChanged(@NonNull android.view.autofill.AutofillId, @Nullable CharSequence);
method public final void notifyViewsDisappeared(@NonNull android.view.autofill.AutofillId, @NonNull long[]);
+ method public final void setContentCaptureContext(@Nullable android.view.contentcapture.ContentCaptureContext);
}
public final class ContentCaptureSessionId implements android.os.Parcelable {
diff --git a/api/removed.txt b/api/removed.txt
index f5bd434c3cc0..c4ed871d0661 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -558,7 +558,7 @@ package android.telephony {
public class TelephonyManager {
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) public java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
- method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 48a450a441a9..0fd21377c7f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1366,6 +1366,7 @@ package android.content {
field public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
field public static final String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
+ field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
field public static final String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_DEFAULT_APP = "android.intent.action.MANAGE_DEFAULT_APP";
field public static final String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
@@ -1580,7 +1581,7 @@ package android.content.pm {
method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method public void sendDeviceCustomizationReadyBroadcast();
method @RequiresPermission(allOf={android.Manifest.permission.SET_PREFERRED_APPLICATIONS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public abstract boolean setDefaultBrowserPackageNameAsUser(String, int);
- method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setDistractingPackageRestrictions(@NonNull String[], @android.content.pm.PackageManager.DistractionRestriction int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setDistractingPackageRestrictions(@NonNull String[], int);
method @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public void setHarmfulAppWarning(@NonNull String, @Nullable CharSequence);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable String);
method @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable android.content.pm.SuspendDialogInfo);
@@ -1658,9 +1659,6 @@ package android.content.pm {
method public abstract void onDexModuleRegistered(String, boolean, String);
}
- @IntDef(flag=true, prefix={"RESTRICTION_"}, value={android.content.pm.PackageManager.RESTRICTION_NONE, android.content.pm.PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS, android.content.pm.PackageManager.RESTRICTION_HIDE_NOTIFICATIONS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface PackageManager.DistractionRestriction {
- }
-
public static interface PackageManager.OnPermissionsChangedListener {
method public void onPermissionsChanged(int);
}
@@ -5783,8 +5781,10 @@ package android.provider {
}
public static interface DeviceConfig.Rollback {
+ field public static final String BOOT_NAMESPACE = "rollback_boot";
field public static final String ENABLE_ROLLBACK_TIMEOUT = "enable_rollback_timeout";
field public static final String NAMESPACE = "rollback";
+ field public static final String ROLLBACK_LIFETIME_IN_MILLIS = "rollback_lifetime_in_millis";
}
public static interface DeviceConfig.Runtime {
@@ -5946,6 +5946,7 @@ package android.provider {
public final class Settings {
field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final String ACTION_LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS = "android.settings.LOCATION_CONTROLLER_EXTRA_PACKAGE_SETTINGS";
+ field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
}
@@ -6301,20 +6302,11 @@ package android.service.autofill.augmented {
}
public abstract class PresentationParams {
- method public int getFlags();
- method @Nullable public android.service.autofill.augmented.PresentationParams.Area getFullArea();
method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
- field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
- field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
- field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
- field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
- field public static final int FLAG_HOST_IME = 16; // 0x10
- field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
}
public abstract static class PresentationParams.Area {
method @NonNull public android.graphics.Rect getBounds();
- method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSubArea(@NonNull android.graphics.Rect);
}
}
@@ -6974,6 +6966,7 @@ package android.telecom {
field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+ field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
field public static final int TTY_MODE_FULL = 1; // 0x1
field public static final int TTY_MODE_HCO = 2; // 0x2
field public static final int TTY_MODE_OFF = 0; // 0x0
@@ -7860,7 +7853,7 @@ package android.telephony {
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean needsOtaServiceProvisioning();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
- method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
@@ -8248,6 +8241,7 @@ package android.telephony.ims {
method public int getServiceType();
method public static int getVideoStateFromCallType(int);
method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean hasKnownUserIntentEmergency();
method public boolean isEmergencyCallTesting();
method public boolean isVideoCall();
method public boolean isVideoPaused();
@@ -8260,6 +8254,7 @@ package android.telephony.ims {
method public void setEmergencyCallTesting(boolean);
method public void setEmergencyServiceCategories(int);
method public void setEmergencyUrns(java.util.List<java.lang.String>);
+ method public void setHasKnownUserIntentEmergency(boolean);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
method public void updateCallType(android.telephony.ims.ImsCallProfile);
method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
@@ -9324,6 +9319,7 @@ package android.view.contentcapture {
public final class ContentCaptureEvent implements android.os.Parcelable {
method public int describeContents();
+ method @Nullable public android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
method public long getEventTime();
method @Nullable public android.view.autofill.AutofillId getId();
method @Nullable public java.util.List<android.view.autofill.AutofillId> getIds();
@@ -9332,6 +9328,7 @@ package android.view.contentcapture {
method @Nullable public android.view.contentcapture.ViewNode getViewNode();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
+ field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6
field public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5; // 0x5
field public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4; // 0x4
field public static final int TYPE_VIEW_APPEARED = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index 1a7e4cb83c52..47d38a7d2f3a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -996,6 +996,7 @@ package android.net {
method public int[] getCapabilities();
method public int[] getTransportTypes();
method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities);
+ field public static final int TRANSPORT_TEST = 7; // 0x7
}
public class NetworkStack {
@@ -1815,6 +1816,7 @@ package android.provider {
public final class Settings {
field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
+ field public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE = "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1
}
@@ -2073,20 +2075,11 @@ package android.service.autofill.augmented {
}
public abstract class PresentationParams {
- method public int getFlags();
- method @Nullable public android.service.autofill.augmented.PresentationParams.Area getFullArea();
method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSuggestionArea();
- field public static final int FLAG_HINT_GRAVITY_BOTTOM = 2; // 0x2
- field public static final int FLAG_HINT_GRAVITY_LEFT = 4; // 0x4
- field public static final int FLAG_HINT_GRAVITY_RIGHT = 8; // 0x8
- field public static final int FLAG_HINT_GRAVITY_TOP = 1; // 0x1
- field public static final int FLAG_HOST_IME = 16; // 0x10
- field public static final int FLAG_HOST_SYSTEM = 32; // 0x20
}
public abstract static class PresentationParams.Area {
method @NonNull public android.graphics.Rect getBounds();
- method @Nullable public android.service.autofill.augmented.PresentationParams.Area getSubArea(@NonNull android.graphics.Rect);
}
}
@@ -2725,6 +2718,7 @@ package android.view.contentcapture {
public final class ContentCaptureEvent implements android.os.Parcelable {
method public int describeContents();
+ method @Nullable public android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
method public long getEventTime();
method @Nullable public android.view.autofill.AutofillId getId();
method @Nullable public java.util.List<android.view.autofill.AutofillId> getIds();
@@ -2733,6 +2727,7 @@ package android.view.contentcapture {
method @Nullable public android.view.contentcapture.ViewNode getViewNode();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
+ field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6
field public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5; // 0x5
field public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4; // 0x4
field public static final int TYPE_VIEW_APPEARED = 1; // 0x1
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index faf2053835fa..f4086557870d 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -76,6 +76,7 @@ cc_defaults {
"src/external/SubsystemSleepStatePuller.cpp",
"src/external/PowerStatsPuller.cpp",
"src/external/ResourceHealthManagerPuller.cpp",
+ "src/external/TrainInfoPuller.cpp",
"src/external/StatsPullerManager.cpp",
"src/external/puller_util.cpp",
"src/logd/LogEvent.cpp",
@@ -238,6 +239,7 @@ cc_test {
"tests/guardrail/StatsdStats_test.cpp",
"tests/metrics/metrics_test_helper.cpp",
"tests/statsd_test_util.cpp",
+ "tests/storage/StorageManager_test.cpp",
"tests/e2e/WakelockDuration_e2e_test.cpp",
"tests/e2e/MetricActivation_e2e_test.cpp",
"tests/e2e/MetricConditionLink_e2e_test.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index b478fed49a54..fb603b9ce163 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -31,6 +31,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionController.h>
+#include <cutils/multiuser.h>
#include <dirent.h>
#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
#include <private/android_filesystem_config.h>
@@ -47,6 +48,7 @@ using namespace android;
using android::base::StringPrintf;
using android::util::FIELD_COUNT_REPEATED;
+using android::util::FIELD_TYPE_INT64;
using android::util::FIELD_TYPE_MESSAGE;
namespace android {
@@ -62,6 +64,8 @@ constexpr const char* kOpUsage = "android:get_usage_stats";
// for StatsDataDumpProto
const int FIELD_ID_REPORTS_LIST = 1;
+// for TrainInfo experiment id serialization
+const int FIELD_ID_EXPERIMENT_ID = 1;
static binder::Status ok() {
return binder::Status::ok();
@@ -1167,6 +1171,56 @@ Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& p
return Status::ok();
}
+Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainName,
+ int64_t trainVersionCode, int options,
+ int32_t state,
+ const std::vector<int64_t>& experimentIds) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ // For testing
+ if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) {
+ return ok();
+ }
+
+ // Caller must be granted these permissions
+ if (!checkCallingPermission(String16(kPermissionDump))) {
+ return exception(binder::Status::EX_SECURITY,
+ StringPrintf("UID %d lacks permission %s", uid, kPermissionDump));
+ }
+ if (!checkCallingPermission(String16(kPermissionUsage))) {
+ return exception(binder::Status::EX_SECURITY,
+ StringPrintf("UID %d lacks permission %s", uid, kPermissionUsage));
+ }
+ // TODO: add verifier permission
+
+ userid_t userId = multiuser_get_user_id(uid);
+
+ bool requiresStaging = options | IStatsManager::FLAG_REQUIRE_STAGING;
+ bool rollbackEnabled = options | IStatsManager::FLAG_ROLLBACK_ENABLED;
+ bool requiresLowLatencyMonitor = options | IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
+
+ ProtoOutputStream proto;
+ for (const auto& expId : experimentIds) {
+ proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
+ (long long)expId);
+ }
+
+ vector<uint8_t> buffer;
+ buffer.resize(proto.size());
+ size_t pos = 0;
+ auto iter = proto.data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&(buffer[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+ LogEvent event(std::string(String8(trainName).string()), trainVersionCode, requiresStaging,
+ rollbackEnabled, requiresLowLatencyMonitor, state, buffer, userId);
+ mProcessor->OnLogEvent(&event);
+ StorageManager::writeTrainInfo(trainVersionCode, buffer);
+ return Status::ok();
+}
+
hardware::Return<void> StatsService::reportSpeakerImpedance(
const SpeakerImpedance& speakerImpedance) {
LogEvent event(getWallClockSec() * NS_PER_SEC, getElapsedRealtimeNs(), speakerImpedance);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 7f10d74ec7d6..d24565a63054 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -31,6 +31,7 @@
#include <android/frameworks/stats/1.0/types.h>
#include <android/os/BnStatsManager.h>
#include <android/os/IStatsCompanionService.h>
+#include <android/os/IStatsManager.h>
#include <binder/IResultReceiver.h>
#include <utils/Looper.h>
@@ -186,6 +187,13 @@ public:
virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override;
/**
+ * Binder call to log BinaryPushStateChanged atom.
+ */
+ virtual Status sendBinaryPushStateChangedAtom(
+ const android::String16& trainName, int64_t trainVersionCode, int options,
+ int32_t state, const std::vector<int64_t>& experimentIds) override;
+
+ /**
* Binder call to get SpeakerImpedance atom.
*/
virtual Return<void> reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) override;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 29f67c7e6f9b..873b772d06ea 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3156,6 +3156,13 @@ message FlagFlipUpdateOccurred {
optional int64 order_id = 2;
}
+/**
+ * Potential experiment ids that goes with a train install.
+ */
+message TrainExperimentIds {
+ repeated int64 experiment_id = 1;
+}
+
/*
* Logs when a binary push state changes.
* Logged by the installer via public api.
@@ -3182,8 +3189,14 @@ message BinaryPushStateChanged {
INSTALL_FAILURE = 6;
INSTALL_CANCELLED = 7;
INSTALLER_ROLLBACK_REQUESTED = 8;
+ INSTALLER_ROLLBACK_SUCCESS = 9;
+ INSTALLER_ROLLBACK_FAILURE = 10;
}
optional State state = 6;
+ // Possible experiment ids for monitoring this push.
+ optional TrainExperimentIds experiment_ids = 7 [(log_mode) = MODE_BYTES];
+ // user id
+ optional int32 user_id = 8;
}
/** Represents USB port overheat event. */
@@ -5511,13 +5524,6 @@ message DeviceIdentifierAccessDenied {
}
/**
- * Potential experiment ids that goes with a train install.
- */
-message TrainExperimentIds {
- repeated int64 experiment_id = 1;
-}
-
-/**
* Pulls the ongoing mainline install train version code.
* Pulled from StatsCompanionService
*/
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ed72b2914a34..98f810fd9a2c 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -29,10 +29,11 @@
#include "../statscompanion_util.h"
#include "PowerStatsPuller.h"
#include "ResourceHealthManagerPuller.h"
-#include "StatsCompanionServicePuller.h"
#include "StatsCallbackPuller.h"
+#include "StatsCompanionServicePuller.h"
#include "StatsPullerManager.h"
#include "SubsystemSleepStatePuller.h"
+#include "TrainInfoPuller.h"
#include "statslog.h"
#include <iostream>
@@ -152,7 +153,7 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
// temperature
{android::util::TEMPERATURE,
- {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
+ {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
// binder_calls
{android::util::BINDER_CALLS,
{.additiveFields = {4, 5, 6, 8, 12},
@@ -231,6 +232,8 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
// PermissionState.
{android::util::DANGEROUS_PERMISSION_STATE,
{.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}},
+ // TrainInfo.
+ {android::util::TRAIN_INFO, {.puller = new TrainInfoPuller()}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/external/TrainInfoPuller.cpp b/cmds/statsd/src/external/TrainInfoPuller.cpp
new file mode 100644
index 000000000000..9d0924297912
--- /dev/null
+++ b/cmds/statsd/src/external/TrainInfoPuller.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include "external/StatsPuller.h"
+
+#include "TrainInfoPuller.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+#include "statslog.h"
+#include "storage/StorageManager.h"
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+TrainInfoPuller::TrainInfoPuller() :
+ StatsPuller(android::util::TRAIN_INFO) {
+}
+
+bool TrainInfoPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ InstallTrainInfo trainInfo;
+ bool ret = StorageManager::readTrainInfo(trainInfo);
+ if (!ret) {
+ ALOGW("Failed to read train info.");
+ return false;
+ }
+ auto event = make_shared<LogEvent>(getWallClockNs(), getElapsedRealtimeNs(), trainInfo);
+ data->push_back(event);
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/TrainInfoPuller.h b/cmds/statsd/src/external/TrainInfoPuller.h
new file mode 100644
index 000000000000..615d02351fd3
--- /dev/null
+++ b/cmds/statsd/src/external/TrainInfoPuller.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads train info from disk.
+ */
+class TrainInfoPuller : public StatsPuller {
+ public:
+ TrainInfoPuller();
+
+ private:
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index b433c41518cc..d661ee8651be 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -478,6 +478,11 @@ void StatsdStats::noteBucketDropped(int64_t metricId) {
getAtomMetricStats(metricId).bucketDropped++;
}
+void StatsdStats::noteBucketUnknownCondition(int64_t metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).bucketUnknownCondition++;
+}
+
void StatsdStats::noteConditionChangeInNextBucket(int64_t metricId) {
lock_guard<std::mutex> lock(mLock);
getAtomMetricStats(metricId).conditionChangeInNextBucket++;
@@ -497,7 +502,7 @@ void StatsdStats::noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayN
std::min(pullStats.minBucketBoundaryDelayNs, timeDelayNs);
}
-StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int metricId) {
+StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int64_t metricId) {
auto atomMetricStatsIter = mAtomMetricStats.find(metricId);
if (atomMetricStatsIter != mAtomMetricStats.end()) {
return atomMetricStatsIter->second;
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 5275c8f34fd0..e039be2b4395 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -409,6 +409,11 @@ public:
void noteBucketBoundaryDelayNs(int64_t metricId, int64_t timeDelayNs);
/**
+ * Number of buckets with unknown condition.
+ */
+ void noteBucketUnknownCondition(int64_t metricId);
+
+ /**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
* to collect stats after reset() has been called.
@@ -458,6 +463,7 @@ public:
long bucketDropped = 0;
int64_t minBucketBoundaryDelayNs = 0;
int64_t maxBucketBoundaryDelayNs = 0;
+ long bucketUnknownCondition = 0;
} AtomMetricStats;
private:
@@ -488,7 +494,7 @@ private:
std::map<int, PulledAtomStats> mPulledAtomStats;
// Maps metric ID to its stats. The size is capped by the number of metrics.
- std::map<int, AtomMetricStats> mAtomMetricStats;
+ std::map<int64_t, AtomMetricStats> mAtomMetricStats;
struct LogLossStats {
LogLossStats(int32_t sec, int32_t count, int32_t error)
@@ -532,7 +538,7 @@ private:
* Get a reference to AtomMetricStats for a metric. If none exists, create it. The reference
* will live as long as `this`.
*/
- StatsdStats::AtomMetricStats& getAtomMetricStats(int metricId);
+ StatsdStats::AtomMetricStats& getAtomMetricStats(int64_t metricId);
FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd);
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 40a4070d2974..dec36b54a1ce 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -20,6 +20,8 @@
#include "stats_log_util.h"
#include "statslog.h"
+#include <binder/IPCThreadState.h>
+
namespace android {
namespace os {
namespace statsd {
@@ -180,6 +182,25 @@ LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedT
}
}
+LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
+ bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
+ const std::vector<uint8_t>& experimentIds, int32_t userId) {
+ mLogdTimestampNs = getWallClockNs();
+ mElapsedTimestampNs = getElapsedRealtimeNs();
+ mTagId = android::util::BINARY_PUSH_STATE_CHANGED;
+ mLogUid = android::IPCThreadState::self()->getCallingUid();
+
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
+ mValues.push_back(
+ FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
+}
+
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
const SpeakerImpedance& speakerImpedance) {
mLogdTimestampNs = wallClockTimestampNs;
@@ -340,6 +361,16 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
}
}
+LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+ const InstallTrainInfo& trainInfo) {
+ mLogdTimestampNs = wallClockTimestampNs;
+ mElapsedTimestampNs = elapsedTimestampNs;
+ mTagId = android::util::TRAIN_INFO;
+ mValues.push_back(
+ FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainInfo.experimentIds)));
+}
+
LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 784376a1580c..111a619760df 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -55,6 +55,11 @@ struct AttributionNodeInternal {
int32_t mUid;
std::string mTag;
};
+
+struct InstallTrainInfo {
+ int64_t trainVersionCode;
+ std::vector<uint8_t> experimentIds;
+};
/**
* Wrapper for the log_msg structure.
*/
@@ -97,6 +102,11 @@ public:
const std::map<int32_t, std::string>& string_map,
const std::map<int32_t, float>& float_map);
+ // Constructs a BinaryPushStateChanged LogEvent from API call.
+ explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging,
+ bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
+ const std::vector<uint8_t>& experimentIds, int32_t userId);
+
explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
const SpeakerImpedance& speakerImpedance);
@@ -127,6 +137,9 @@ public:
explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
const VendorAtom& vendorAtom);
+ explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+ const InstallTrainInfo& installTrainInfo);
+
~LogEvent();
/**
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 350745b2c326..5707de544648 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -250,7 +250,7 @@ void CountMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
void CountMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
- mCondition = conditionMet;
+ mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
}
bool CountMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 6c1c47bbc093..da6b97cc4e59 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -433,7 +433,7 @@ void DurationMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondit
void DurationMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
- mCondition = conditionMet;
+ mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
flushIfNeededLocked(eventTime);
for (auto& whatIt : mCurrentSlicedDurationTrackerMap) {
for (auto& pair : whatIt.second) {
@@ -767,12 +767,13 @@ void DurationMetricProducer::onMatchedLogEventLocked(const size_t matcherIndex,
!mSameConditionDimensionsInTracker,
!mHasLinksToAllConditionDimensionsInTracker,
&dimensionKeysInCondition);
- condition = (conditionState == ConditionState::kTrue);
+ condition = conditionState == ConditionState::kTrue;
if (mDimensionsInCondition.empty() && condition) {
dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
}
} else {
- condition = mCondition;
+ // TODO: The unknown condition state is not handled here, we should fix it.
+ condition = mCondition == ConditionState::kTrue;
if (condition) {
dimensionKeysInCondition.insert(DEFAULT_DIMENSION_KEY);
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 1b830a3f69f5..ec561b527025 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -137,6 +137,7 @@ private:
FRIEND_TEST(DurationMetricTrackerTest, TestNoCondition);
FRIEND_TEST(DurationMetricTrackerTest, TestNonSlicedCondition);
+ FRIEND_TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState);
FRIEND_TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade);
FRIEND_TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket);
FRIEND_TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade);
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 7e695a69988f..3b4af6533e34 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -132,7 +132,7 @@ void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTime) {
VLOG("Metric %lld onConditionChanged", (long long)mMetricId);
- mCondition = conditionMet;
+ mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
}
void EventMetricProducer::onMatchedLogEventInternalLocked(
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index d56a355f15d6..837d532f7e09 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -320,15 +320,15 @@ void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
// When the metric wants to do random sampling and there is already one gauge atom for the
// current bucket, do not do it again.
case GaugeMetric::RANDOM_ONE_SAMPLE: {
- triggerPuller = mCondition && mCurrentSlicedBucket->empty();
+ triggerPuller = mCondition == ConditionState::kTrue && mCurrentSlicedBucket->empty();
break;
}
case GaugeMetric::CONDITION_CHANGE_TO_TRUE: {
- triggerPuller = mCondition;
+ triggerPuller = mCondition == ConditionState::kTrue;
break;
}
case GaugeMetric::FIRST_N_SAMPLES: {
- triggerPuller = mCondition;
+ triggerPuller = mCondition == ConditionState::kTrue;
break;
}
default:
@@ -364,7 +364,7 @@ void GaugeMetricProducer::onConditionChangedLocked(const bool conditionMet,
const int64_t eventTimeNs) {
VLOG("GaugeMetric %lld onConditionChanged", (long long)mMetricId);
flushIfNeededLocked(eventTimeNs);
- mCondition = conditionMet;
+ mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse;
if (mIsPulled && mTriggerAtomId == -1) {
pullAndMatchEventsLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
@@ -377,7 +377,7 @@ void GaugeMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition
flushIfNeededLocked(eventTimeNs);
// If the condition is sliced, mCondition is true if any of the dimensions is true. And we will
// pull for every dimension.
- mCondition = overallCondition;
+ mCondition = overallCondition ? ConditionState::kTrue : ConditionState::kFalse;
if (mIsPulled && mTriggerAtomId == -1) {
pullAndMatchEventsLocked(eventTimeNs);
} // else: Push mode. No need to proactively pull the gauge data.
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 11075685b7fa..4cf5333947d3 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -45,7 +45,8 @@ void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const Lo
&dimensionKeysInCondition);
condition = (conditionState == ConditionState::kTrue);
} else {
- condition = mCondition;
+ // TODO: The unknown condition state is not handled here, we should fix it.
+ condition = mCondition == ConditionState::kTrue;
}
if (mDimensionsInCondition.empty() && condition) {
@@ -107,7 +108,8 @@ void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedT
if (it == mEventActivationMap.end()) {
return;
}
- if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT) {
+ if (mActivationType == MetricActivation::ACTIVATE_ON_BOOT &&
+ it->second.state == ActivationState::kNotActive) {
it->second.state = ActivationState::kActiveOnBoot;
return;
}
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 849cb76ec392..8ab3b0680276 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -59,7 +59,7 @@ public:
mTimeBaseNs(timeBaseNs),
mCurrentBucketStartTimeNs(timeBaseNs),
mCurrentBucketNum(0),
- mCondition(conditionIndex >= 0 ? false : true),
+ mCondition(conditionIndex >= 0 ? ConditionState::kUnknown : ConditionState::kTrue),
mConditionSliced(false),
mWizard(wizard),
mConditionTrackerIndex(conditionIndex),
@@ -315,7 +315,7 @@ protected:
int64_t mBucketSizeNs;
- bool mCondition;
+ ConditionState mCondition;
bool mConditionSliced;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 851ae9962d09..bc7c8727284f 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -154,7 +154,7 @@ ValueMetricProducer::ValueMetricProducer(
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
// Kicks off the puller immediately if condition is true and diff based.
- if (mIsPulled && mCondition && mUseDiff) {
+ if (mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
pullAndMatchEventsLocked(startTimeNs);
}
VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
@@ -341,17 +341,21 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
flushIfNeededLocked(eventTimeNs);
// Pull on condition changes.
- if (mIsPulled && (mCondition != condition)) {
+ bool conditionChanged = mCondition != condition;
+ bool unknownToFalse = mCondition == ConditionState::kUnknown
+ && condition == ConditionState::kFalse;
+ // We do not need to pull when we go from unknown to false.
+ if (mIsPulled && conditionChanged && !unknownToFalse) {
pullAndMatchEventsLocked(eventTimeNs);
}
// when condition change from true to false, clear diff base but don't
// reset other counters as we may accumulate more value in the bucket.
- if (mUseDiff && mCondition && !condition) {
+ if (mUseDiff && mCondition == ConditionState::kTrue && condition == ConditionState::kFalse) {
resetBase();
}
- mCondition = condition;
+ mCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
}
void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
@@ -372,7 +376,7 @@ int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTime
void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
bool pullSuccess, int64_t originalPullTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mCondition) {
+ if (mCondition == ConditionState::kTrue) {
if (!pullSuccess) {
// If the pull failed, we won't be able to compute a diff.
invalidateCurrentBucket();
@@ -725,6 +729,10 @@ void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
}
void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+ if (mCondition == ConditionState::kUnknown) {
+ StatsdStats::getInstance().noteBucketUnknownCondition(mMetricId);
+ }
+
VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
(int)mCurrentSlicedBucket.size());
int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index f7428a50b3da..09b8fed60dcc 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -425,6 +425,7 @@ message StatsdStatsReport {
optional int64 bucket_dropped = 8;
optional int64 min_bucket_boundary_delay_ns = 9;
optional int64 max_bucket_boundary_delay_ns = 10;
+ optional int64 bucket_unknown_condition = 11;
}
repeated AtomMetricStats atom_metric_stats = 17;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 01043a2143f0..ca645e186614 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -84,6 +84,7 @@ const int FIELD_ID_INVALIDATED_BUCKET = 7;
const int FIELD_ID_BUCKET_DROPPED = 8;
const int FIELD_ID_MIN_BUCKET_BOUNDARY_DELAY_NS = 9;
const int FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS = 10;
+const int FIELD_ID_BUCKET_UNKNOWN_CONDITION = 11;
namespace {
@@ -489,11 +490,11 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>
protoOutput->end(token);
}
-void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+void writeAtomMetricStatsToStream(const std::pair<int64_t, StatsdStats::AtomMetricStats> &pair,
util::ProtoOutputStream *protoOutput) {
uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
FIELD_COUNT_REPEATED);
- protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (int32_t)pair.first);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_ID, (long long)pair.first);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
(long long)pair.second.hardDimensionLimitReached);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
@@ -512,6 +513,8 @@ void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricSt
(long long)pair.second.minBucketBoundaryDelayNs);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_BUCKET_BOUNDARY_DELAY_NS,
(long long)pair.second.maxBucketBoundaryDelayNs);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_UNKNOWN_CONDITION,
+ (long long)pair.second.bucketUnknownCondition);
protoOutput->end(token);
}
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index dcea0e653e22..59d4865f8977 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -74,7 +74,7 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>
util::ProtoOutputStream* protoOutput);
// Helper function to write AtomMetricStats to ProtoOutputStream
-void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+void writeAtomMetricStatsToStream(const std::pair<int64_t, StatsdStats::AtomMetricStats> &pair,
util::ProtoOutputStream *protoOutput);
template<class T>
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 90f641a34b85..165e57c73743 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -38,10 +38,13 @@ using std::map;
#define STATS_DATA_DIR "/data/misc/stats-data"
#define STATS_SERVICE_DIR "/data/misc/stats-service"
+#define TRAIN_INFO_DIR "/data/misc/train-info"
// for ConfigMetricsReportList
const int FIELD_ID_REPORTS = 2;
+std::mutex StorageManager::sTrainInfoMutex;
+
using android::base::StringPrintf;
using std::unique_ptr;
@@ -92,6 +95,71 @@ void StorageManager::writeFile(const char* file, const void* buffer, int numByte
close(fd);
}
+bool StorageManager::writeTrainInfo(int64_t trainVersionCode,
+ const std::vector<uint8_t>& experimentIds) {
+ std::lock_guard<std::mutex> lock(sTrainInfoMutex);
+
+ deleteAllFiles(TRAIN_INFO_DIR);
+
+ string file_name = StringPrintf("%s/%lld", TRAIN_INFO_DIR, (long long)trainVersionCode);
+
+ int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ VLOG("Attempt to access %s but failed", file_name.c_str());
+ return false;
+ }
+
+ size_t result = write(fd, experimentIds.data(), experimentIds.size());
+ if (result == experimentIds.size()) {
+ VLOG("Successfully wrote %s", file_name.c_str());
+ } else {
+ VLOG("Failed to write %s", file_name.c_str());
+ return false;
+ }
+
+ result = fchown(fd, AID_STATSD, AID_STATSD);
+ if (result) {
+ VLOG("Failed to chown %s to statsd", file_name.c_str());
+ return false;
+ }
+
+ close(fd);
+ return true;
+}
+
+bool StorageManager::readTrainInfo(InstallTrainInfo& trainInfo) {
+ std::lock_guard<std::mutex> lock(sTrainInfoMutex);
+
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(TRAIN_INFO_DIR), closedir);
+
+ if (dir == NULL) {
+ VLOG("Directory does not exist: %s", TRAIN_INFO_DIR);
+ return false;
+ }
+
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] == '.') {
+ continue;
+ }
+ trainInfo.trainVersionCode = StrToInt64(name);
+ string fullPath = StringPrintf("%s/%s", TRAIN_INFO_DIR, name);
+ int fd = open(fullPath.c_str(), O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ string str;
+ if (android::base::ReadFdToString(fd, &str)) {
+ close(fd);
+ std::copy(str.begin(), str.end(), std::back_inserter(trainInfo.experimentIds));
+ VLOG("Read train info file successful: %s", fullPath.c_str());
+ return true;
+ }
+ }
+ close(fd);
+ }
+ return false;
+}
+
void StorageManager::deleteFile(const char* file) {
if (remove(file) != 0) {
VLOG("Attempt to delete %s but is not found", file);
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index dcf3bb607380..d6df8674e59b 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -29,6 +29,11 @@ namespace statsd {
using android::util::ProtoOutputStream;
+struct TrainInfo {
+ int64_t trainVersionCode;
+ std::vector<uint8_t> experimentIds;
+};
+
class StorageManager : public virtual RefBase {
public:
/**
@@ -37,6 +42,16 @@ public:
static void writeFile(const char* file, const void* buffer, int numBytes);
/**
+ * Writes train info.
+ */
+ static bool writeTrainInfo(int64_t trainVersionCode, const std::vector<uint8_t>& experimentIds);
+
+ /**
+ * Reads train info.
+ */
+ static bool readTrainInfo(InstallTrainInfo& trainInfo);
+
+ /**
* Reads the file content to the buffer.
*/
static bool readFileToString(const char* file, string* content);
@@ -109,6 +124,8 @@ private:
* Prints disk usage statistics about a directory related to statsd.
*/
static void printDirStats(int out, const char* path);
+
+ static std::mutex sTrainInfoMutex;
};
} // namespace statsd
diff --git a/cmds/statsd/statsd.rc b/cmds/statsd/statsd.rc
index e0cbd5d25716..a98ecd586b42 100644
--- a/cmds/statsd/statsd.rc
+++ b/cmds/statsd/statsd.rc
@@ -27,3 +27,4 @@ on post-fs-data
mkdir /data/misc/stats-data/ 0770 statsd system
mkdir /data/misc/stats-service/ 0770 statsd system
mkdir /data/misc/stats-active-metric/ 0770 statsd system
+ mkdir /data/misc/train-info/ 0770 statsd system
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index b54096441d3f..b294cad1802c 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -117,6 +117,7 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+ durationProducer.mCondition = ConditionState::kFalse;
EXPECT_FALSE(durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
@@ -140,6 +141,51 @@ TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
EXPECT_EQ(1LL, buckets2[0].mDuration);
}
+TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ int64_t bucketStartTimeNs = 10000000000;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+
+ DurationMetric metric;
+ metric.set_id(1);
+ metric.set_bucket(ONE_MINUTE);
+ metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+
+ int tagId = 1;
+ LogEvent event1(tagId, bucketStartTimeNs + 1);
+ event1.init();
+ LogEvent event2(tagId, bucketStartTimeNs + 2);
+ event2.init();
+ LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+ event3.init();
+ LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+ event4.init();
+
+ FieldMatcher dimensions;
+ DurationMetricProducer durationProducer(
+ kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+
+ EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
+ EXPECT_FALSE(durationProducer.isConditionSliced());
+
+ durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+ durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+ durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+ EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+
+ durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
+ durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
+ durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
+ durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+ EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+ const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+ EXPECT_EQ(1UL, buckets2.size());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
+ EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
+ EXPECT_EQ(1LL, buckets2[0].mDuration);
+}
+
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
/**
* The duration starts from the first bucket, through the two partial buckets (10-70sec),
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 572b1991f426..7e7ffeda8053 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -2176,7 +2176,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = true;
+ valueProducer.mCondition = ConditionState::kTrue;
vector<shared_ptr<LogEvent>> allData;
valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
@@ -2226,7 +2226,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = false;
+ valueProducer.mCondition = ConditionState::kFalse;
// Max delay is set to 0 so pull will exceed max delay.
valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
@@ -2257,7 +2257,7 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
eventMatcherWizard, tagId, bucket2StartTimeNs,
bucket2StartTimeNs, pullerManager);
- valueProducer.mCondition = false;
+ valueProducer.mCondition = ConditionState::kFalse;
// Event should be skipped since it is from previous bucket.
// Pull should not be called.
@@ -2299,7 +2299,7 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = false;
+ valueProducer.mCondition = ConditionState::kFalse;
valueProducer.mHasGlobalBase = false;
valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
@@ -2351,7 +2351,7 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = true;
+ valueProducer.mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2429,7 +2429,7 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = false;
+ valueProducer.mCondition = ConditionState::kFalse;
valueProducer.onConditionChanged(true, bucket2StartTimeNs + 2);
EXPECT_EQ(true, valueProducer.mCurrentBucketIsInvalid);
EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
@@ -2481,7 +2481,7 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = true;
+ valueProducer.mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2564,7 +2564,7 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.mCondition = true;
+ valueProducer.mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
diff --git a/cmds/statsd/tests/storage/StorageManager_test.cpp b/cmds/statsd/tests/storage/StorageManager_test.cpp
new file mode 100644
index 000000000000..f66de0518f80
--- /dev/null
+++ b/cmds/statsd/tests/storage/StorageManager_test.cpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include "src/storage/StorageManager.h"
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using namespace testing;
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
+using testing::Contains;
+
+TEST(StorageManagerTest, TrainInfoReadWriteTest) {
+ InstallTrainInfo trainInfo;
+ trainInfo.trainVersionCode = 12345;
+ const char* expIds = "test_ids";
+ trainInfo.experimentIds.assign(expIds, expIds + strlen(expIds));
+
+ StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.experimentIds);
+
+ InstallTrainInfo result;
+ StorageManager::readTrainInfo(result);
+ EXPECT_EQ(trainInfo.trainVersionCode, result.trainVersionCode);
+ EXPECT_EQ(trainInfo.experimentIds.size(), result.experimentIds.size());
+ EXPECT_EQ(trainInfo.experimentIds, result.experimentIds);
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index b72ce8977128..dc2ed4cc0d69 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -542,8 +542,6 @@ Landroid/net/IConnectivityManager;->getTetherableWifiRegexs()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->getTetheredIfaces()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->getTetheringErroredIfaces()[Ljava/lang/String;
Landroid/net/IConnectivityManager;->startLegacyVpn(Lcom/android/internal/net/VpnProfile;)V
-Landroid/net/INetd$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetd;
-Landroid/net/INetd;->interfaceAddAddress(Ljava/lang/String;Ljava/lang/String;I)V
Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
Landroid/net/INetworkPolicyListener$Stub;-><init>()V
Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager;
@@ -2825,7 +2823,6 @@ Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V
Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V
-Lcom/android/internal/telephony/GsmCdmaCallTracker;->dialThreeWay(Ljava/lang/String;)Lcom/android/internal/telephony/Connection;
Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V
Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V
Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1a728c12e138..6908ca27480c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2101,7 +2101,8 @@ class ContextImpl extends Context {
}
private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName,
- int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) {
+ int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo,
+ String[] overlayDirs) {
final String[] splitResDirs;
final ClassLoader classLoader;
try {
@@ -2113,7 +2114,7 @@ class ContextImpl extends Context {
return ResourcesManager.getInstance().getResources(activityToken,
pi.getResDir(),
splitResDirs,
- pi.getOverlayDirs(),
+ overlayDirs,
pi.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfig,
@@ -2131,9 +2132,11 @@ class ContextImpl extends Context {
new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
final int displayId = getDisplayId();
-
+ // overlayDirs is retrieved directly from ApplicationInfo since ActivityThread may have
+ // a LoadedApk containing Resources with stale overlays for a remote application.
+ final String[] overlayDirs = application.resourceDirs;
c.setResources(createResources(mActivityToken, pi, null, displayId, null,
- getDisplayAdjustments(displayId).getCompatibilityInfo()));
+ getDisplayAdjustments(displayId).getCompatibilityInfo(), overlayDirs));
if (c.mResources != null) {
return c;
}
@@ -2168,7 +2171,7 @@ class ContextImpl extends Context {
final int displayId = getDisplayId();
c.setResources(createResources(mActivityToken, pi, null, displayId, null,
- getDisplayAdjustments(displayId).getCompatibilityInfo()));
+ getDisplayAdjustments(displayId).getCompatibilityInfo(), pi.getOverlayDirs()));
if (c.mResources != null) {
return c;
}
@@ -2218,7 +2221,8 @@ class ContextImpl extends Context {
final int displayId = getDisplayId();
context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
- overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
+ overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
+ mPackageInfo.getOverlayDirs()));
return context;
}
@@ -2233,7 +2237,8 @@ class ContextImpl extends Context {
final int displayId = display.getDisplayId();
context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
- null, getDisplayAdjustments(displayId).getCompatibilityInfo()));
+ null, getDisplayAdjustments(displayId).getCompatibilityInfo(),
+ mPackageInfo.getOverlayDirs()));
context.mDisplay = display;
return context;
}
@@ -2416,7 +2421,7 @@ class ContextImpl extends Context {
ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
null, null, 0, null, null);
context.setResources(createResources(null, packageInfo, null, displayId, null,
- packageInfo.getCompatibilityInfo()));
+ packageInfo.getCompatibilityInfo(), packageInfo.getOverlayDirs()));
context.updateDisplay(displayId);
return context;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 807b7f2ac349..cca8bd00b646 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -101,7 +101,6 @@ import android.net.IConnectivityManager;
import android.net.IEthernetManager;
import android.net.IIpMemoryStore;
import android.net.IIpSecService;
-import android.net.INetd;
import android.net.INetworkPolicyManager;
import android.net.IpMemoryStore;
import android.net.IpSecManager;
@@ -330,11 +329,10 @@ final class SystemServiceRegistry {
return new ConnectivityManager(context, service);
}});
- registerService(Context.NETD_SERVICE, INetd.class, new StaticServiceFetcher<INetd>() {
+ registerService(Context.NETD_SERVICE, IBinder.class, new StaticServiceFetcher<IBinder>() {
@Override
- public INetd createService() throws ServiceNotFoundException {
- return INetd.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.NETD_SERVICE));
+ public IBinder createService() throws ServiceNotFoundException {
+ return ServiceManager.getServiceOrThrow(Context.NETD_SERVICE);
}
});
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index d781a96420c7..a965dde5a1a4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1790,6 +1790,35 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.MANAGE_APP_PERMISSIONS";
/**
+ * Activity action: Launch UI to manage a specific permissions of an app.
+ * <p>
+ * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission
+ * will be managed by the launched UI.
+ * </p>
+ * <p>
+ * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission
+ * that should be managed by the launched UI.
+ * </p>
+ * <p>
+ * <li> {@link #EXTRA_USER} specifies the UserHandle of the user that owns the app.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ *
+ * @see #EXTRA_PACKAGE_NAME
+ * @see #EXTRA_PERMISSION_NAME
+ * @see #EXTRA_USER
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_APP_PERMISSION =
+ "android.intent.action.MANAGE_APP_PERMISSION";
+
+ /**
* Activity action: Launch UI to manage permissions.
* <p>
* Input: Nothing.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index eaf6c5a9d1cc..3ea78df6ae39 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5910,24 +5910,24 @@ public abstract class PackageManager {
/**
* Flag to denote no restrictions. This should be used to clear any restrictions that may have
* been previously set for the package.
- * @see PackageManager.DistractionRestriction
* @hide
+ * @see #setDistractingPackageRestrictions(String[], int)
*/
@SystemApi
public static final int RESTRICTION_NONE = 0x0;
/**
* Flag to denote that a package should be hidden from any suggestions to the user.
- * @see PackageManager.DistractionRestriction
* @hide
+ * @see #setDistractingPackageRestrictions(String[], int)
*/
@SystemApi
public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 0x00000001;
/**
* Flag to denote that a package's notifications should be hidden.
- * @see PackageManager.DistractionRestriction
* @hide
+ * @see #setDistractingPackageRestrictions(String[], int)
*/
@SystemApi
public static final int RESTRICTION_HIDE_NOTIFICATIONS = 0x00000002;
@@ -5939,7 +5939,6 @@ public abstract class PackageManager {
* @see #setDistractingPackageRestrictions(String[], int)
* @hide
*/
- @SystemApi
@IntDef(flag = true, prefix = {"RESTRICTION_"}, value = {
RESTRICTION_NONE,
RESTRICTION_HIDE_FROM_SUGGESTIONS,
@@ -5957,14 +5956,16 @@ public abstract class PackageManager {
* <p>The caller must hold {@link android.Manifest.permission#SUSPEND_APPS} to use this API.
*
* @param packages Packages to mark as distracting.
- * @param restrictionFlags Any combination of {@link DistractionRestriction restrictions} to
- * impose on the given packages. {@link #RESTRICTION_NONE} can be used
- * to clear any existing restrictions.
+ * @param restrictionFlags Any combination of restrictions to impose on the given packages.
+ * {@link #RESTRICTION_NONE} can be used to clear any existing
+ * restrictions.
* @return A list of packages that could not have the {@code restrictionFlags} set. The system
* may prevent restricting critical packages to preserve normal device function.
*
- * @see DistractionRestriction
* @hide
+ * @see #RESTRICTION_NONE
+ * @see #RESTRICTION_HIDE_FROM_SUGGESTIONS
+ * @see #RESTRICTION_HIDE_NOTIFICATIONS
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.SUSPEND_APPS)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0abd5eaaf2aa..0f67262bf901 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4848,7 +4848,7 @@ public class PackageParser {
}
/**
- * Sets every the max aspect ratio of every child activity that doesn't already have an aspect
+ * Sets every the min aspect ratio of every child activity that doesn't already have an aspect
* ratio set.
*/
private void setMinAspectRatio(Package owner) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2aca55aacf7a..68d36de19963 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -678,11 +678,20 @@ public class ConnectivityManager {
@Deprecated
public static final int TYPE_VPN = 17;
+ /**
+ * A network that is exclusively meant to be used for testing
+ *
+ * @deprecated Use {@link NetworkCapabilities} instead.
+ * @hide
+ */
+ @Deprecated
+ public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused.
+
/** {@hide} */
- public static final int MAX_RADIO_TYPE = TYPE_VPN;
+ public static final int MAX_RADIO_TYPE = TYPE_TEST;
/** {@hide} */
- public static final int MAX_NETWORK_TYPE = TYPE_VPN;
+ public static final int MAX_NETWORK_TYPE = TYPE_TEST;
private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 62cf7d7ceb25..b9d49c14f6c6 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -36,8 +36,9 @@ public class InterfaceConfiguration implements Parcelable {
private LinkAddress mAddr;
private HashSet<String> mFlags = Sets.newHashSet();
- private static final String FLAG_UP = INetd.IF_STATE_UP;
- private static final String FLAG_DOWN = INetd.IF_STATE_DOWN;
+ // Must be kept in sync with constant in INetd.aidl
+ private static final String FLAG_UP = "up";
+ private static final String FLAG_DOWN = "down";
private static final String[] EMPTY_STRING_ARRAY = new String[0];
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 7e9bda14b199..1d2d81dc4fbe 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -597,6 +597,7 @@ public final class NetworkCapabilities implements Parcelable {
TRANSPORT_VPN,
TRANSPORT_WIFI_AWARE,
TRANSPORT_LOWPAN,
+ TRANSPORT_TEST,
})
public @interface Transport { }
@@ -635,10 +636,18 @@ public final class NetworkCapabilities implements Parcelable {
*/
public static final int TRANSPORT_LOWPAN = 6;
+ /**
+ * Indicates this network uses a Test-only virtual interface as a transport.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final int TRANSPORT_TEST = 7;
+
/** @hide */
public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
/** @hide */
- public static final int MAX_TRANSPORT = TRANSPORT_LOWPAN;
+ public static final int MAX_TRANSPORT = TRANSPORT_TEST;
/** @hide */
public static boolean isValidTransport(@Transport int transportType) {
@@ -652,7 +661,8 @@ public final class NetworkCapabilities implements Parcelable {
"ETHERNET",
"VPN",
"WIFI_AWARE",
- "LOWPAN"
+ "LOWPAN",
+ "TEST"
};
/**
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 5ab34e9aa6e8..bf272625e713 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -92,16 +92,6 @@ public class NetworkPolicyManager {
public static final int MASK_ALL_NETWORKS = 0b11110000;
public static final int FIREWALL_RULE_DEFAULT = 0;
- public static final int FIREWALL_RULE_ALLOW = INetd.FIREWALL_RULE_ALLOW;
- public static final int FIREWALL_RULE_DENY = INetd.FIREWALL_RULE_DENY;
-
- public static final int FIREWALL_TYPE_WHITELIST = INetd.FIREWALL_WHITELIST;
- public static final int FIREWALL_TYPE_BLACKLIST = INetd.FIREWALL_BLACKLIST;
-
- public static final int FIREWALL_CHAIN_NONE = INetd.FIREWALL_CHAIN_NONE;
- public static final int FIREWALL_CHAIN_DOZABLE = INetd.FIREWALL_CHAIN_DOZABLE;
- public static final int FIREWALL_CHAIN_STANDBY = INetd.FIREWALL_CHAIN_STANDBY;
- public static final int FIREWALL_CHAIN_POWERSAVE = INetd.FIREWALL_CHAIN_POWERSAVE;
public static final String FIREWALL_CHAIN_NAME_NONE = "none";
public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 8813e400bee0..cc241b3b7756 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -25,16 +25,11 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
-import android.gamedriver.GameDriverProto.Blacklist;
-import android.gamedriver.GameDriverProto.Blacklists;
import android.opengl.EGL14;
import android.provider.Settings;
-import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
-import com.android.framework.protobuf.InvalidProtocolBufferException;
-
import dalvik.system.VMRuntime;
import java.io.File;
@@ -69,8 +64,7 @@ public class GraphicsEnvironment {
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
- private static final String GAME_DRIVER_BLACKLIST_FLAG = "blacklist";
- private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP;
+ private static final String GAME_DRIVER_WHITELIST_ALL = "*";
private ClassLoader mClassLoader;
private String mLayerPath;
@@ -630,43 +624,23 @@ public class GraphicsEnvironment {
final boolean isOptIn =
getGlobalSettingsString(null, coreSettings,
Settings.Global.GAME_DRIVER_OPT_IN_APPS).contains(packageName);
- if (!isOptIn
- && !getGlobalSettingsString(null, coreSettings,
- Settings.Global.GAME_DRIVER_WHITELIST).contains(packageName)) {
+ final List<String> whitelist = getGlobalSettingsString(null, coreSettings,
+ Settings.Global.GAME_DRIVER_WHITELIST);
+ if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0
+ && !whitelist.contains(packageName)) {
if (DEBUG) {
Log.w(TAG, packageName + " is not on the whitelist.");
}
return false;
}
- if (!isOptIn) {
- // At this point, the application is on the whitelist only, check whether it's
- // on the blacklist, terminate early when it's on the blacklist.
- try {
- // TODO(b/121350991) Switch to DeviceConfig with property listener.
- final String base64String =
- coreSettings.getString(Settings.Global.GAME_DRIVER_BLACKLIST);
- if (base64String != null && !base64String.isEmpty()) {
- final Blacklists blacklistsProto =
- Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS));
- final List<Blacklist> blacklists = blacklistsProto.getBlacklistsList();
- final long driverVersionCode = driverAppInfo.longVersionCode;
- for (Blacklist blacklist : blacklists) {
- if (blacklist.getVersionCode() == driverVersionCode) {
- for (String pkgName : blacklist.getPackageNamesList()) {
- if (pkgName == packageName) {
- return false;
- }
- }
- break;
- }
- }
- }
- } catch (InvalidProtocolBufferException e) {
- if (DEBUG) {
- Log.w(TAG, "Can't parse blacklist, skip and continue...");
- }
- }
+ // If the application is not opted-in and check whether it's on the blacklist,
+ // terminate early if it's on the blacklist and fallback to system driver.
+ if (!isOptIn
+ && getGlobalSettingsString(null, coreSettings,
+ Settings.Global.GAME_DRIVER_BLACKLIST)
+ .contains(ai.packageName)) {
+ return false;
}
}
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index f1bba1ab2977..6d4c5a034b54 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -196,4 +196,25 @@ interface IStatsManager {
* Requires Manifest.permission.DUMP and Manifest.permission.PACKAGE_USAGE_STATS
*/
oneway void unregisterPullerCallback(int atomTag, String packageName);
+
+ /**
+ * The install requires staging.
+ */
+ const int FLAG_REQUIRE_STAGING = 0x01;
+
+ /**
+ * Rollback is enabled with this install.
+ */
+ const int FLAG_ROLLBACK_ENABLED = 0x02;
+
+ /**
+ * Requires low latency monitoring.
+ */
+ const int FLAG_REQUIRE_LOW_LATENCY_MONITOR = 0x04;
+
+ /**
+ * Logs an event for binary push for module updates.
+ */
+ oneway void sendBinaryPushStateChangedAtom(in String trainName, in long trainVersionCode,
+ in int options, in int state, in long[] experimentId);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2ecf9d1159f0..cfe2d28f1024 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1784,7 +1784,7 @@ public final class PowerManager {
*
* see {@link #registerThermalStatusCallback}
*/
- public void unregisterThermalStatusCallback(ThermalStatusCallback callback) {
+ public void unregisterThermalStatusCallback(@NonNull ThermalStatusCallback callback) {
Preconditions.checkNotNull(callback, "callback cannnot be null");
synchronized (this) {
if (mThermalService == null) {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 104b61dc410d..7eb03007ee6a 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -316,10 +316,17 @@ public final class DeviceConfig {
public interface Rollback {
String NAMESPACE = "rollback";
+ String BOOT_NAMESPACE = "rollback_boot";
+
/**
* Timeout in milliseconds for enabling package rollback.
*/
String ENABLE_ROLLBACK_TIMEOUT = "enable_rollback_timeout";
+
+ /**
+ * The lifetime duration of rollback packages in millis
+ */
+ String ROLLBACK_LIFETIME_IN_MILLIS = "rollback_lifetime_in_millis";
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 452d09dc2e6e..d925d7ee2676 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1657,6 +1657,30 @@ public final class Settings {
public static final String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS =
"android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
+
+ /**
+ * Activity Action: Show screen that let user select enable (or disable) Content Capture.
+ * <p>
+ * Input: Nothing.
+ *
+ * <p>
+ * Output: {@link android.app.Activity#RESULT_OK} if user enabled Content Capture,
+ * {@link android.app.Activity#RESULT_CANCELED} if user disabled it, cancelled, or if the caller
+ * is not the Content Capture service associated with the user.
+ *
+ * <p>
+ * <b>NOTE: </b> Caller should call
+ * {@link android.view.contentcapture.ContentCaptureManager#isContentCaptureFeatureEnabled()}
+ * first to check whether the feature is already enabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_ENABLE_CONTENT_CAPTURE =
+ "android.settings.REQUEST_ENABLE_CONTENT_CAPTURE";
+
// End of Intent actions for Settings
/**
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 81d066d3d656..8695da237f97 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -61,8 +61,6 @@ import java.util.List;
*/
@SystemApi
@TestApi
-// TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-// in the same package as the test, and that module is compiled with SDK=test_current
public abstract class AugmentedAutofillService extends Service {
private static final String TAG = AugmentedAutofillService.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index f2a7a35b2825..b989dd9cd4eb 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -31,8 +31,6 @@ import android.util.Log;
*/
@SystemApi
@TestApi
-//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-//in the same package as the test, and that module is compiled with SDK=test_current
public final class FillCallback {
private static final String TAG = FillCallback.class.getSimpleName();
diff --git a/core/java/android/service/autofill/augmented/FillController.java b/core/java/android/service/autofill/augmented/FillController.java
index d7bc893f884a..67f23d599e1d 100644
--- a/core/java/android/service/autofill/augmented/FillController.java
+++ b/core/java/android/service/autofill/augmented/FillController.java
@@ -38,10 +38,8 @@ import java.util.List;
*/
@SystemApi
@TestApi
-//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-//in the same package as the test, and that module is compiled with SDK=test_current
public final class FillController {
- private static final String TAG = "FillController";
+ private static final String TAG = FillController.class.getSimpleName();
private final AutofillProxy mProxy;
diff --git a/core/java/android/service/autofill/augmented/FillRequest.java b/core/java/android/service/autofill/augmented/FillRequest.java
index af9905f480df..9a97bb203f5a 100644
--- a/core/java/android/service/autofill/augmented/FillRequest.java
+++ b/core/java/android/service/autofill/augmented/FillRequest.java
@@ -31,8 +31,6 @@ import android.view.autofill.AutofillValue;
@SystemApi
// TODO(b/123100811): pass a requestId and/or sessionId?
@TestApi
-// TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-// in the same package as the test, and that module is compiled with SDK=test_current
public final class FillRequest {
final AutofillProxy mProxy;
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index f1e904a7d8bc..2ac406c5b08c 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -30,8 +30,6 @@ import java.util.List;
*/
@SystemApi
@TestApi
-//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-//in the same package as the test, and that module is compiled with SDK=test_current
public final class FillResponse {
private final FillWindow mFillWindow;
@@ -53,8 +51,6 @@ public final class FillResponse {
*/
@SystemApi
@TestApi
- //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
- //in the same package as the test, and that module is compiled with SDK=test_current
public static final class Builder {
private FillWindow mFillWindow;
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 40e3a1219501..6e06754e7b8a 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -63,10 +63,8 @@ import java.io.PrintWriter;
*/
@SystemApi
@TestApi
-//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-//in the same package as the test, and that module is compiled with SDK=test_current
public final class FillWindow implements AutoCloseable {
- private static final String TAG = "FillWindow";
+ private static final String TAG = FillWindow.class.getSimpleName();
private final Object mLock = new Object();
private final CloseGuard mCloseGuard = CloseGuard.get();
diff --git a/core/java/android/service/autofill/augmented/PresentationParams.java b/core/java/android/service/autofill/augmented/PresentationParams.java
index 1fb9032c9af5..334487dd6ab4 100644
--- a/core/java/android/service/autofill/augmented/PresentationParams.java
+++ b/core/java/android/service/autofill/augmented/PresentationParams.java
@@ -15,32 +15,19 @@
*/
package android.service.autofill.augmented;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.graphics.Rect;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
-import android.util.DebugUtils;
import android.view.View;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
/**
* Abstraction of a "Smart Suggestion" component responsible to embed the autofill UI provided by
- * the intelligence service.
- *
- * <p>The Smart Suggestion can embed the autofill UI in 3 distinct places:
- *
- * <ul>
- * <li>A small area associated with suggestions (like a small strip in the top of the IME),
- * returned by {@link #getSuggestionArea()}
- * <li>The full area (like the full IME window), returned by {@link #getFullArea()}
- * <li>A subset of the aforementioned areas, returned by {@link Area#getSubArea(Rect)}
- * </ul>
+ * the augmented autofill service.
*
* <p>The Smart Suggestion is represented by a {@link Area} object that contains the
* dimensions the smart suggestion window, so the service can use it to calculate the size of the
@@ -50,54 +37,8 @@ import java.lang.annotation.RetentionPolicy;
*/
@SystemApi
@TestApi
-//TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
-//in the same package as the test, and that module is compiled with SDK=test_current
public abstract class PresentationParams {
- /**
- * Flag indicating the Smart Suggestion is hosted in the top of its container.
- */
- public static final int FLAG_HINT_GRAVITY_TOP = 0x1;
-
- /**
- * Flag indicating the Smart Suggestion is hosted in the bottom of its container.
- */
- public static final int FLAG_HINT_GRAVITY_BOTTOM = 0x2;
-
- /**
- * Flag indicating the Smart Suggestion is hosted in the left of its container.
- */
- public static final int FLAG_HINT_GRAVITY_LEFT = 0x4;
-
- /**
- * Flag indicating the Smart Suggestion is hosted in the right of its container.
- */
- public static final int FLAG_HINT_GRAVITY_RIGHT = 0x8;
-
- /**
- * Flag indicating the Smart Suggestion is hosted by the IME.
- */
- public static final int FLAG_HOST_IME = 0x10;
-
- /**
- * Flag indicating the Smart Suggestion is hosted by the Android System as a floating popup
- * window.
- */
- public static final int FLAG_HOST_SYSTEM = 0x20;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "FLAG_" }, value = {
- FLAG_HINT_GRAVITY_TOP,
- FLAG_HINT_GRAVITY_BOTTOM,
- FLAG_HINT_GRAVITY_LEFT,
- FLAG_HINT_GRAVITY_RIGHT,
- FLAG_HOST_IME,
- FLAG_HOST_SYSTEM
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface Flags {}
-
-
// /** @hide */
PresentationParams() {}
@@ -112,40 +53,7 @@ public abstract class PresentationParams {
return null;
}
- /**
- * Gets the full area for the of the Smart Suggestion provider.
- *
- * @return full dimensions, or {@code null} if the Smart Suggestion provider does not support
- * embeding the UI on its full area.
- */
- @Nullable
- public Area getFullArea() {
- return null;
- }
-
- /**
- * Gets flags associated with the Smart Suggestion.
- *
- * @return any combination of {@link #FLAG_HINT_GRAVITY_TOP},
- * {@link #FLAG_HINT_GRAVITY_BOTTOM}, {@link #FLAG_HINT_GRAVITY_LEFT},
- * {@link #FLAG_HINT_GRAVITY_RIGHT}, {@link #FLAG_HOST_IME}, or
- * {@link #FLAG_HOST_SYSTEM},
- */
- public @Flags int getFlags() {
- return 0;
- }
-
- /** @hide */
- void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
- final int flags = getFlags();
- if (flags > 0) {
- pw.print(prefix); pw.print("flags: "); pw.println(flagsToString(flags));
- }
- }
-
- private static String flagsToString(int flags) {
- return DebugUtils.flagsToString(PresentationParams.class, "FLAG_", flags);
- }
+ abstract void dump(String prefix, PrintWriter pw);
/**
* Area associated with a {@link PresentationParams Smart Suggestions} provider.
@@ -154,8 +62,6 @@ public abstract class PresentationParams {
*/
@SystemApi
@TestApi
- //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
- //in the same package as the test, and that module is compiled with SDK=test_current
public abstract static class Area {
/** @hide */
@@ -176,24 +82,6 @@ public abstract class PresentationParams {
return mBounds;
}
- /**
- * Gets a subarea limited by given boundaries.
- *
- * @param bounds boundaries relative to this Area.
- *
- * @return new subarea, or {@code null} if the Smart Suggestion host does not support such
- * subaarea.
- *
- * @throws IllegalArgumentException if the {@code bounds} is not fully-contained inside this
- * full Area.
- *
- */
- @Nullable
- public Area getSubArea(@NonNull Rect bounds) {
- // TODO(b/123100712): implement / check boundaries / throw IAE / add unit test
- return null;
- }
-
@Override
public String toString() {
return mBounds.toString();
@@ -220,13 +108,7 @@ public abstract class PresentationParams {
}
@Override
- public int getFlags() {
- return FLAG_HOST_SYSTEM | FLAG_HINT_GRAVITY_BOTTOM;
- }
-
- @Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
- super.dump(prefix, pw);
pw.print(prefix); pw.print("area: "); pw.println(mSuggestionArea);
}
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index c98f09e13d97..d2f98599e9a6 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -339,7 +339,7 @@ public abstract class ContentCaptureService extends Service {
}
switch (event.getType()) {
case ContentCaptureEvent.TYPE_SESSION_STARTED:
- final ContentCaptureContext clientContext = event.getClientContext();
+ final ContentCaptureContext clientContext = event.getContentCaptureContext();
clientContext.setParentSessionId(event.getParentSessionId());
mSessionUids.put(sessionIdString, uid);
onCreateContentCaptureSession(clientContext, sessionId);
@@ -383,8 +383,8 @@ public abstract class ContentCaptureService extends Service {
}
final Integer rightUid = mSessionUids.get(sessionId);
if (rightUid == null) {
- if (DEBUG) {
- Log.d(TAG, "handleIsRightCallerFor(" + event + "): no session for " + sessionId
+ if (VERBOSE) {
+ Log.v(TAG, "handleIsRightCallerFor(" + event + "): no session for " + sessionId
+ ": " + mSessionUids);
}
// Just ignore, as the session could have been finished already
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 551bb8ada044..954dc3943019 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -372,6 +372,13 @@ public class StatusBarNotification implements Parcelable {
/**
* @hide
*/
+ public void clearPackageContext() {
+ mContext = null;
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage
public Context getPackageContext(Context context) {
if (mContext == null) {
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index ace4bf477af6..29ced3eda4ec 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -16,7 +16,14 @@
package android.util;
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.PACKAGE_USAGE_STATS;
+
+import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.app.IActivityManager;
+import android.content.Context;
import android.os.IStatsManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -31,7 +38,10 @@ public final class StatsLog extends StatsLogInternal {
private static IStatsManager sService;
- private StatsLog() {}
+ private static Object sLogLock = new Object();
+
+ private StatsLog() {
+ }
/**
* Logs a start event.
@@ -40,11 +50,13 @@ public final class StatsLog extends StatsLogInternal {
* @return True if the log request was sent to statsd.
*/
public static boolean logStart(int label) {
- synchronized (StatsLog.class) {
+ synchronized (sLogLock) {
try {
IStatsManager service = getIStatsManagerLocked();
if (service == null) {
- if (DEBUG) Slog.d(TAG, "Failed to find statsd when logging start");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to find statsd when logging start");
+ }
return false;
}
service.sendAppBreadcrumbAtom(label,
@@ -52,7 +64,9 @@ public final class StatsLog extends StatsLogInternal {
return true;
} catch (RemoteException e) {
sService = null;
- if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when logging start");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to connect to statsd when logging start");
+ }
return false;
}
}
@@ -65,18 +79,22 @@ public final class StatsLog extends StatsLogInternal {
* @return True if the log request was sent to statsd.
*/
public static boolean logStop(int label) {
- synchronized (StatsLog.class) {
+ synchronized (sLogLock) {
try {
IStatsManager service = getIStatsManagerLocked();
if (service == null) {
- if (DEBUG) Slog.d(TAG, "Failed to find statsd when logging stop");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to find statsd when logging stop");
+ }
return false;
}
service.sendAppBreadcrumbAtom(label, StatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP);
return true;
} catch (RemoteException e) {
sService = null;
- if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when logging stop");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to connect to statsd when logging stop");
+ }
return false;
}
}
@@ -89,11 +107,13 @@ public final class StatsLog extends StatsLogInternal {
* @return True if the log request was sent to statsd.
*/
public static boolean logEvent(int label) {
- synchronized (StatsLog.class) {
+ synchronized (sLogLock) {
try {
IStatsManager service = getIStatsManagerLocked();
if (service == null) {
- if (DEBUG) Slog.d(TAG, "Failed to find statsd when logging event");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to find statsd when logging event");
+ }
return false;
}
service.sendAppBreadcrumbAtom(
@@ -101,7 +121,51 @@ public final class StatsLog extends StatsLogInternal {
return true;
} catch (RemoteException e) {
sService = null;
- if (DEBUG) Slog.d(TAG, "Failed to connect to statsd when logging event");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to connect to statsd when logging event");
+ }
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Logs an event for binary push for module updates.
+ *
+ * @param trainName name of install train.
+ * @param trainVersionCode version code of the train.
+ * @param options optional flags about this install.
+ * @param state current install state.
+ * @param experimentIds experiment ids.
+ * @return True if the log request was sent to statsd.
+ */
+ @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
+ public static boolean logBinaryPushStateChanged(@NonNull String trainName,
+ long trainVersionCode, int options, int state,
+ @NonNull long[] experimentIds) {
+ synchronized (sLogLock) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (service == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to find statsd when logging event");
+ }
+ return false;
+ }
+ int userId = IActivityManager.Stub.asInterface(
+ ServiceManager.getService("activity"))
+ .getCurrentUser()
+ .id;
+ service.sendBinaryPushStateChangedAtom(
+ trainName, trainVersionCode, options, state, experimentIds);
+ return true;
+ } catch (RemoteException e) {
+ sService = null;
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Failed to connect to StatsCompanionService when logging "
+ + "BinaryPushStateChanged");
+ }
return false;
}
}
@@ -118,7 +182,7 @@ public final class StatsLog extends StatsLogInternal {
/**
* Add a log to the stats log.
*
- * @param id The id of the atom
+ * @param id The id of the atom
* @param params The parameters of the atom's message.
*/
public static void write(int id, @NonNull Object... params) {
@@ -128,4 +192,13 @@ public final class StatsLog extends StatsLogInternal {
(boolean) params[4], (int) params[5]);
}
}
+
+ private static void enforceDumpCallingPermission(Context context) {
+ context.enforceCallingPermission(android.Manifest.permission.DUMP, "Need DUMP permission.");
+ }
+
+ private static void enforcesageStatsCallingPermission(Context context) {
+ context.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
+ "Need PACKAGE_USAGE_STATS permission.");
+ }
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 62ed901c5e06..f37c9162d98a 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -336,7 +336,7 @@ public final class AccessibilityInteractionController {
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
final View root = findViewByAccessibilityId(accessibilityViewId);
- if (root != null) {
+ if (root != null && isShown(root)) {
mPrefetcher.prefetchAccessibilityNodeInfos(
root, virtualDescendantId, flags, infos, arguments);
}
@@ -448,7 +448,7 @@ public final class AccessibilityInteractionController {
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
final View root = findViewByAccessibilityId(accessibilityViewId);
- if (root != null) {
+ if (root != null && isShown(root)) {
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
if (provider != null) {
infos = provider.findAccessibilityNodeInfosByText(text,
@@ -531,7 +531,7 @@ public final class AccessibilityInteractionController {
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
final View root = findViewByAccessibilityId(accessibilityViewId);
- if (root != null) {
+ if (root != null && isShown(root)) {
switch (focusType) {
case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY: {
View host = mViewRootImpl.mAccessibilityFocusedHost;
@@ -621,7 +621,7 @@ public final class AccessibilityInteractionController {
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
final View root = findViewByAccessibilityId(accessibilityViewId);
- if (root != null) {
+ if (root != null && isShown(root)) {
View nextView = root.focusSearch(direction);
if (nextView != null) {
next = nextView.createAccessibilityNodeInfo();
@@ -676,7 +676,7 @@ public final class AccessibilityInteractionController {
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
final View target = findViewByAccessibilityId(accessibilityViewId);
- if (target != null) {
+ if (target != null && isShown(target)) {
if (action == R.id.accessibilityActionClickOnClickableSpan) {
// Handle this hidden action separately
succeeded = handleClickableSpanActionUiThread(
@@ -759,9 +759,7 @@ public final class AccessibilityInteractionController {
if (accessibilityId == AccessibilityNodeInfo.ROOT_ITEM_ID) {
return mViewRootImpl.mView;
} else {
- final View foundView =
- AccessibilityNodeIdManager.getInstance().findView(accessibilityId);
- return isShown(foundView) ? foundView : null;
+ return AccessibilityNodeIdManager.getInstance().findView(accessibilityId);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ba1b51780291..2b440dc80cfd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9487,7 +9487,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Gets the session used to notify Content Capture events.
*
* @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
- * inherited by ancestore, default session or {@code null} if content capture is disabled for
+ * inherited by ancestors, default session or {@code null} if content capture is disabled for
* this view.
*/
@Nullable
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 5e5c8265f782..f93ac4ce7d16 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1782,10 +1782,6 @@ public final class AutofillManager {
/**
* Explicitly limits augmented autofill to the given packages and activities.
*
- * <p>When the whitelist is set, it overrides the values passed to
- * {@link #setActivityAugmentedAutofillEnabled(ComponentName, boolean)}
- * and {@link #setPackageAugmentedAutofillEnabled(String, boolean)}.
- *
* <p>To reset the whitelist, call it passing {@code null} to both arguments.
*
* <p>Useful when the service wants to restrict augmented autofill to a category of apps, like
@@ -1803,8 +1799,6 @@ public final class AutofillManager {
*/
@SystemApi
@TestApi
- //TODO(b/122654591): @TestApi is needed because CtsAutoFillServiceTestCases hosts the service
- //in the same package as the test, and that module is compiled with SDK=test_current
public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
@Nullable List<ComponentName> activities) {
// TODO(b/123100824): implement
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index acb81e086461..13e8a6584218 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -20,10 +20,6 @@ import android.annotation.Nullable;
import android.view.autofill.AutofillId;
import android.view.contentcapture.ViewNode.ViewStructureImpl;
-import com.android.internal.util.Preconditions;
-
-import java.io.PrintWriter;
-
/**
* A session that is explicitly created by the app (and hence is a descendant of
* {@link MainContentCaptureSession}).
@@ -35,21 +31,11 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
@NonNull
private final ContentCaptureSession mParent;
- /**
- * {@link ContentCaptureContext} set by client, or {@code null} when it's the
- * {@link ContentCaptureManager#getMainContentCaptureSession() default session} for the
- * context.
- *
- * @hide
- */
- @NonNull
- private final ContentCaptureContext mClientContext;
-
/** @hide */
protected ChildContentCaptureSession(@NonNull ContentCaptureSession parent,
@NonNull ContentCaptureContext clientContext) {
+ super(clientContext);
mParent = parent;
- mClientContext = Preconditions.checkNotNull(clientContext);
}
@Override
@@ -73,6 +59,11 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
}
@Override
+ public void updateContentCaptureContext(@Nullable ContentCaptureContext context) {
+ getMainCaptureSession().notifyContextUpdated(mId, context);
+ }
+
+ @Override
void onDestroy() {
getMainCaptureSession().notifyChildSessionFinished(mParent.mId, mId);
}
@@ -101,13 +92,4 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
boolean isContentCaptureEnabled() {
return getMainCaptureSession().isContentCaptureEnabled();
}
-
- @Override
- void dump(String prefix, PrintWriter pw) {
- if (mClientContext != null) {
- // NOTE: we don't dump clientContent because it could have PII
- pw.print(prefix); pw.println("hasClientContext");
- }
- super.dump(prefix, pw);
- }
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 22254cd94059..9cdbefac3d1d 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -91,13 +91,22 @@ public final class ContentCaptureEvent implements Parcelable {
*/
public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5;
+ /**
+ * Called after a call to
+ * {@link ContentCaptureSession#setContentCaptureContext(ContentCaptureContext)}.
+ *
+ * <p>The passed context is available through {@link #getContentCaptureContext()}.
+ */
+ public static final int TYPE_CONTEXT_UPDATED = 6;
+
/** @hide */
@IntDef(prefix = { "TYPE_" }, value = {
TYPE_VIEW_APPEARED,
TYPE_VIEW_DISAPPEARED,
TYPE_VIEW_TEXT_CHANGED,
TYPE_INITIAL_VIEW_TREE_APPEARING,
- TYPE_INITIAL_VIEW_TREE_APPEARED
+ TYPE_INITIAL_VIEW_TREE_APPEARED,
+ TYPE_CONTEXT_UPDATED
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType{}
@@ -193,12 +202,13 @@ public final class ContentCaptureEvent implements Parcelable {
}
/**
- * Used by {@link #TYPE_SESSION_STARTED}.
+ * Gets the {@link ContentCaptureContext} set calls to
+ * {@link ContentCaptureSession#setContentCaptureContext(ContentCaptureContext)}.
*
- * @hide
+ * <p>Only set on {@link #TYPE_CONTEXT_UPDATED} events.
*/
@Nullable
- public ContentCaptureContext getClientContext() {
+ public ContentCaptureContext getContentCaptureContext() {
return mClientContext;
}
@@ -220,8 +230,8 @@ public final class ContentCaptureEvent implements Parcelable {
* Gets the type of the event.
*
* @return one of {@link #TYPE_VIEW_APPEARED}, {@link #TYPE_VIEW_DISAPPEARED},
- * {@link #TYPE_VIEW_TEXT_CHANGED}, {@link #TYPE_INITIAL_VIEW_TREE_APPEARING}, or
- * {@link #TYPE_INITIAL_VIEW_TREE_APPEARED}.
+ * {@link #TYPE_VIEW_TEXT_CHANGED}, {@link #TYPE_INITIAL_VIEW_TREE_APPEARING},
+ * {@link #TYPE_INITIAL_VIEW_TREE_APPEARED}, or {@link #TYPE_CONTEXT_UPDATED}.
*/
public @EventType int getType() {
return mType;
@@ -299,6 +309,10 @@ public final class ContentCaptureEvent implements Parcelable {
if (mText != null) {
pw.print(", text="); pw.println(getSanitizedString(mText));
}
+ if (mClientContext != null) {
+ pw.print(", context="); mClientContext.dump(pw); pw.println();
+
+ }
}
@Override
@@ -325,6 +339,9 @@ public final class ContentCaptureEvent implements Parcelable {
if (mText != null) {
string.append(", text=").append(getSanitizedString(mText));
}
+ if (mClientContext != null) {
+ string.append(", context=").append(mClientContext);
+ }
return string.append(']').toString();
}
@@ -345,7 +362,7 @@ public final class ContentCaptureEvent implements Parcelable {
if (mType == TYPE_SESSION_STARTED || mType == TYPE_SESSION_FINISHED) {
parcel.writeString(mParentSessionId);
}
- if (mType == TYPE_SESSION_STARTED) {
+ if (mType == TYPE_SESSION_STARTED || mType == TYPE_CONTEXT_UPDATED) {
parcel.writeParcelable(mClientContext, flags);
}
}
@@ -375,7 +392,7 @@ public final class ContentCaptureEvent implements Parcelable {
if (type == TYPE_SESSION_STARTED || type == TYPE_SESSION_FINISHED) {
event.setParentSessionId(parcel.readString());
}
- if (type == TYPE_SESSION_STARTED) {
+ if (type == TYPE_SESSION_STARTED || type == TYPE_CONTEXT_UPDATED) {
event.setClientContext(parcel.readParcelable(null));
}
return event;
@@ -404,6 +421,8 @@ public final class ContentCaptureEvent implements Parcelable {
return "INITIAL_VIEW_HIERARCHY_STARTED";
case TYPE_INITIAL_VIEW_TREE_APPEARED:
return "INITIAL_VIEW_HIERARCHY_FINISHED";
+ case TYPE_CONTEXT_UPDATED:
+ return "CONTEXT_UPDATED";
default:
return "UKNOWN_TYPE: " + type;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index e028961692f9..b8d3fa6f4404 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -166,6 +166,14 @@ public abstract class ContentCaptureSession implements AutoCloseable {
private ContentCaptureSessionId mContentCaptureSessionId;
/**
+ * {@link ContentCaptureContext} set by client, or {@code null} when it's the
+ * {@link ContentCaptureManager#getMainContentCaptureSession() default session} for the
+ * context.
+ */
+ @Nullable
+ private ContentCaptureContext mClientContext;
+
+ /**
* List of children session.
*/
@Nullable
@@ -183,6 +191,12 @@ public abstract class ContentCaptureSession implements AutoCloseable {
mId = Preconditions.checkNotNull(id);
}
+ // Used by ChildCOntentCaptureSession
+ ContentCaptureSession(@NonNull ContentCaptureContext initialContext) {
+ this();
+ mClientContext = Preconditions.checkNotNull(initialContext);
+ }
+
/** @hide */
@NonNull
abstract MainContentCaptureSession getMainCaptureSession();
@@ -240,6 +254,30 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract void flush(@FlushReason int reason);
/**
+ * Sets the {@link ContentCaptureContext} associated with the session.
+ *
+ * <p>Typically used to change the context associated with the default session from an activity.
+ */
+ public final void setContentCaptureContext(@Nullable ContentCaptureContext context) {
+ mClientContext = context;
+ updateContentCaptureContext(context);
+ }
+
+ abstract void updateContentCaptureContext(@Nullable ContentCaptureContext context);
+
+ /**
+ * Gets the {@link ContentCaptureContext} associated with the session.
+ *
+ * @return context set on constructor or by
+ * {@link #setContentCaptureContext(ContentCaptureContext)}, or {@code null} if never
+ * explicitly set.
+ */
+ @Nullable
+ public final ContentCaptureContext getContentCaptureContext() {
+ return mClientContext;
+ }
+
+ /**
* Destroys this session, flushing out all pending notifications to the service.
*
* <p>Once destroyed, any new notification will be dropped.
@@ -424,6 +462,9 @@ public abstract class ContentCaptureSession implements AutoCloseable {
@CallSuper
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
pw.print(prefix); pw.print("id: "); pw.println(mId);
+ if (mClientContext != null) {
+ pw.print(prefix); mClientContext.dump(pw); pw.println();
+ }
synchronized (mLock) {
pw.print(prefix); pw.print("destroyed: "); pw.println(mDestroyed);
if (mChildren != null && !mChildren.isEmpty()) {
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 810c967ce2c8..d949f45ba5e6 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -15,6 +15,7 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_CONTEXT_UPDATED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_INITIAL_VIEW_TREE_APPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_INITIAL_VIEW_TREE_APPEARING;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
@@ -269,11 +270,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
private void sendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
final int eventType = event.getType();
if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
- if (!hasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) {
+ if (!hasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED
+ && eventType != ContentCaptureEvent.TYPE_CONTEXT_UPDATED) {
// TODO(b/120494182): comment when this could happen (dialogs?)
Log.v(TAG, "handleSendEvent(" + getDebugState() + ", "
+ ContentCaptureEvent.getTypeAsString(eventType)
- + "): session not started yet");
+ + "): dropping because session not started yet");
return;
}
if (mDisabled.get()) {
@@ -476,6 +478,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
}
+ @Override
+ public void updateContentCaptureContext(@Nullable ContentCaptureContext context) {
+ notifyContextUpdated(mId, context);
+ }
+
/**
* Resets the buffer and return a {@link ParceledListSlice} with the previous events.
*/
@@ -613,6 +620,12 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
}
+ void notifyContextUpdated(@NonNull String sessionId,
+ @Nullable ContentCaptureContext context) {
+ sendEvent(new ContentCaptureEvent(sessionId, TYPE_CONTEXT_UPDATED)
+ .setClientContext(context));
+ }
+
@Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2171fc52a0ba..3555822b1f1f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -760,7 +760,7 @@ public class WebView extends AbsoluteLayout
* <p>
* The {@code encoding} parameter specifies whether the data is base64 or URL
* encoded. If the data is base64 encoded, the value of the encoding
- * parameter must be 'base64'. HTML can be encoded with {@link
+ * parameter must be {@code "base64"}. HTML can be encoded with {@link
* android.util.Base64#encodeToString(byte[],int)} like so:
* <pre>
* String unencodedHtml =
@@ -768,11 +768,15 @@ public class WebView extends AbsoluteLayout
* String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING);
* webView.loadData(encodedHtml, "text/html", "base64");
* </pre>
- * <p>
+ * <p class="note">
* For all other values of {@code encoding} (including {@code null}) it is assumed that the
* data uses ASCII encoding for octets inside the range of safe URL characters and use the
* standard %xx hex encoding of URLs for octets outside that range. See <a
* href="https://tools.ietf.org/html/rfc3986#section-2.2">RFC 3986</a> for more information.
+ * Applications targeting {@link android.os.Build.VERSION_CODES#Q} or later must either use
+ * base64 or encode any {@code #} characters in the content as {@code %23}, otherwise they
+ * will be treated as the end of the content and the remaining text used as a document
+ * fragment identifier.
* <p>
* The {@code mimeType} parameter specifies the format of the data.
* If WebView can't handle the specified MIME type, it will download the data.
@@ -820,7 +824,8 @@ public class WebView extends AbsoluteLayout
* <p>
* If the base URL uses the data scheme, this method is equivalent to
* calling {@link #loadData(String,String,String) loadData()} and the
- * historyUrl is ignored, and the data will be treated as part of a data: URL.
+ * historyUrl is ignored, and the data will be treated as part of a data: URL,
+ * including the requirement that the content be URL-encoded or base64 encoded.
* If the base URL uses any other scheme, then the data will be loaded into
* the WebView as a plain string (i.e. not part of a data URL) and any URL-encoded
* entities in the string will not be decoded.
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e8172172f5d2..8f007594dd67 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -355,9 +355,16 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
colorType = kN32_SkColorType;
}
+ sk_sp<SkColorSpace> colorSpace;
+ if (colorType == kAlpha_8_SkColorType) {
+ colorSpace = nullptr;
+ } else {
+ colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
+ }
+
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
- GraphicsJNI::getNativeColorSpace(colorSpacePtr)));
+ colorSpace));
sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
if (!nativeBitmap) {
@@ -385,15 +392,17 @@ static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
case kRGB_565_SkColorType:
dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
break;
- case kRGBA_F16_SkColorType:
- // The caller does not have an opportunity to pass a dst color space. Assume that
- // they want linear sRGB.
- dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
+ case kAlpha_8_SkColorType:
+ dstInfo = dstInfo.makeColorSpace(nullptr);
break;
default:
break;
}
+ if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
+ dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
+ }
+
if (!dst->setInfo(dstInfo)) {
return false;
}
@@ -608,14 +617,6 @@ static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
return static_cast<jint>(bitmap->getGenerationID());
}
-static jboolean Bitmap_isConfigF16(JNIEnv* env, jobject, jlong bitmapHandle) {
- LocalScopedBitmap bitmap(bitmapHandle);
- if (bitmap->info().colorType() == kRGBA_F16_SkColorType) {
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
LocalScopedBitmap bitmap(bitmapHandle);
if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
@@ -684,9 +685,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
const uint32_t colorSpaceSize = p->readUint32();
sk_sp<SkColorSpace> colorSpace;
- if (kRGBA_F16_SkColorType == colorType) {
- colorSpace = SkColorSpace::MakeSRGBLinear();
- } else if (colorSpaceSize > 0) {
+ if (colorSpaceSize > 0) {
if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
"%d bytes\n", colorSpaceSize);
@@ -811,7 +810,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
p->writeInt32(bitmap.colorType());
p->writeInt32(bitmap.alphaType());
SkColorSpace* colorSpace = bitmap.colorSpace();
- if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
+ if (colorSpace != nullptr) {
sk_sp<SkData> data = colorSpace->serialize();
size_t size = data->size();
p->writeUint32(size);
@@ -924,44 +923,14 @@ static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
}
-static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
- jfloatArray xyzArray, jfloatArray paramsArray) {
-
+static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
LocalScopedBitmap bitmapHolder(bitmapHandle);
- if (!bitmapHolder.valid()) return JNI_FALSE;
+ if (!bitmapHolder.valid()) return nullptr;
SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
- if (colorSpace == nullptr) return JNI_FALSE;
-
- skcms_Matrix3x3 xyzMatrix;
- if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
-
- jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
- xyz[0] = xyzMatrix.vals[0][0];
- xyz[1] = xyzMatrix.vals[1][0];
- xyz[2] = xyzMatrix.vals[2][0];
- xyz[3] = xyzMatrix.vals[0][1];
- xyz[4] = xyzMatrix.vals[1][1];
- xyz[5] = xyzMatrix.vals[2][1];
- xyz[6] = xyzMatrix.vals[0][2];
- xyz[7] = xyzMatrix.vals[1][2];
- xyz[8] = xyzMatrix.vals[2][2];
- env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
-
- skcms_TransferFunction transferParams;
- if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
-
- jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
- params[0] = transferParams.a;
- params[1] = transferParams.b;
- params[2] = transferParams.c;
- params[3] = transferParams.d;
- params[4] = transferParams.e;
- params[5] = transferParams.f;
- params[6] = transferParams.g;
- env->ReleaseFloatArrayElements(paramsArray, params, 0);
+ if (colorSpace == nullptr) return nullptr;
- return JNI_TRUE;
+ return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
}
static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
@@ -1174,13 +1143,6 @@ static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitm
return createJavaGraphicBuffer(env, buffer);
}
-static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) {
- LocalScopedBitmap srcBitmapHandle(srcBitmapPtr);
- LocalScopedBitmap dstBitmapHandle(dstBitmapPtr);
-
- dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace());
-}
-
static jboolean Bitmap_isImmutable(jlong bitmapHandle) {
LocalScopedBitmap bitmapHolder(bitmapHandle);
if (!bitmapHolder.valid()) return JNI_FALSE;
@@ -1215,7 +1177,6 @@ static const JNINativeMethod gBitmapMethods[] = {
{ "nativeErase", "(JJJ)V", (void*)Bitmap_eraseLong },
{ "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
{ "nativeConfig", "(J)I", (void*)Bitmap_config },
- { "nativeIsConfigF16", "(J)Z", (void*)Bitmap_isConfigF16 },
{ "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
{ "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
{ "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
@@ -1248,12 +1209,10 @@ static const JNINativeMethod gBitmapMethods[] = {
(void*) Bitmap_wrapHardwareBufferBitmap },
{ "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
(void*) Bitmap_createGraphicBufferHandle },
- { "nativeGetColorSpace", "(J[F[F)Z", (void*)Bitmap_getColorSpace },
+ { "nativeComputeColorSpace", "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
{ "nativeSetColorSpace", "(JJ)V", (void*)Bitmap_setColorSpace },
{ "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
{ "nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear},
- { "nativeCopyColorSpace", "(JJ)V",
- (void*)Bitmap_copyColorSpace },
{ "nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
// ------------ @CriticalNative ----------------
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 70e6604fddeb..4ba4540f7dbc 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -307,7 +307,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
env->SetObjectField(options, gOptions_outConfigFieldID, config);
env->SetObjectField(options, gOptions_outColorSpaceFieldID,
- GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
+ GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType));
if (onlyDecodeSize) {
return nullptr;
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index d65f324d1065..9c07e2d64c6e 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -215,7 +215,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
env->SetObjectField(options, gOptions_outConfigFieldID, config);
env->SetObjectField(options, gOptions_outColorSpaceFieldID,
- GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
+ GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType));
}
// If we may have reused a bitmap, we need to indicate that the pixels have changed.
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 6570992b4b23..2987c5ed56b5 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -187,6 +187,8 @@ static jmethodID gColorSpaceRGB_constructorMethodID;
static jclass gColorSpace_Named_class;
static jfieldID gColorSpace_Named_sRGBFieldID;
+static jfieldID gColorSpace_Named_ExtendedSRGBFieldID;
+static jfieldID gColorSpace_Named_LinearSRGBFieldID;
static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
static jclass gTransferParameters_class;
@@ -412,67 +414,78 @@ jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)
///////////////////////////////////////////////////////////////////////////////
-jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+jobject GraphicsJNI::getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
SkColorType decodeColorType) {
- jobject colorSpace = nullptr;
+ if (!decodeColorSpace || decodeColorType == kAlpha_8_SkColorType) {
+ return nullptr;
+ }
- // No need to match, we know what the output color space will be
+ // Special checks for the common sRGB cases and their extended variants.
+ jobject namedCS = nullptr;
+ sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
if (decodeColorType == kRGBA_F16_SkColorType) {
- jobject linearExtendedSRGB = env->GetStaticObjectField(
- gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_getMethodID, linearExtendedSRGB);
- } else {
- // Same here, no need to match
+ // An F16 Bitmap will always report that it is EXTENDED if
+ // it matches a ColorSpace that has an EXTENDED variant.
if (decodeColorSpace->isSRGB()) {
- jobject sRGB = env->GetStaticObjectField(
- gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_getMethodID, sRGB);
- } else if (decodeColorSpace.get() != nullptr) {
- // Try to match against known RGB color spaces using the CIE XYZ D50
- // conversion matrix and numerical transfer function parameters
- skcms_Matrix3x3 xyzMatrix;
- LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
-
- skcms_TransferFunction transferParams;
- // We can only handle numerical transfer functions at the moment
- LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
-
- jobject params = env->NewObject(gTransferParameters_class,
- gTransferParameters_constructorMethodID,
- transferParams.a, transferParams.b, transferParams.c,
- transferParams.d, transferParams.e, transferParams.f,
- transferParams.g);
-
- jfloatArray xyzArray = env->NewFloatArray(9);
- jfloat xyz[9] = {
- xyzMatrix.vals[0][0],
- xyzMatrix.vals[1][0],
- xyzMatrix.vals[2][0],
- xyzMatrix.vals[0][1],
- xyzMatrix.vals[1][1],
- xyzMatrix.vals[2][1],
- xyzMatrix.vals[0][2],
- xyzMatrix.vals[1][2],
- xyzMatrix.vals[2][2]
- };
- env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
-
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_matchMethodID, xyzArray, params);
-
- if (colorSpace == nullptr) {
- // We couldn't find an exact match, let's create a new color space
- // instance with the 3x3 conversion matrix and transfer function
- colorSpace = env->NewObject(gColorSpaceRGB_class,
- gColorSpaceRGB_constructorMethodID,
- env->NewStringUTF("Unknown"), xyzArray, params);
- }
-
- env->DeleteLocalRef(xyzArray);
+ namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
+ gColorSpace_Named_ExtendedSRGBFieldID);
+ } else if (decodeColorSpace == srgbLinear.get()) {
+ namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
+ gColorSpace_Named_LinearExtendedSRGBFieldID);
}
+ } else if (decodeColorSpace->isSRGB()) {
+ namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
+ gColorSpace_Named_sRGBFieldID);
+ } else if (decodeColorSpace == srgbLinear.get()) {
+ namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
+ gColorSpace_Named_LinearSRGBFieldID);
+ }
+
+ if (namedCS) {
+ return env->CallStaticObjectMethod(gColorSpace_class, gColorSpace_getMethodID, namedCS);
}
+
+ // Try to match against known RGB color spaces using the CIE XYZ D50
+ // conversion matrix and numerical transfer function parameters
+ skcms_Matrix3x3 xyzMatrix;
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
+
+ skcms_TransferFunction transferParams;
+ // We can only handle numerical transfer functions at the moment
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+
+ jobject params = env->NewObject(gTransferParameters_class,
+ gTransferParameters_constructorMethodID,
+ transferParams.a, transferParams.b, transferParams.c,
+ transferParams.d, transferParams.e, transferParams.f,
+ transferParams.g);
+
+ jfloatArray xyzArray = env->NewFloatArray(9);
+ jfloat xyz[9] = {
+ xyzMatrix.vals[0][0],
+ xyzMatrix.vals[1][0],
+ xyzMatrix.vals[2][0],
+ xyzMatrix.vals[0][1],
+ xyzMatrix.vals[1][1],
+ xyzMatrix.vals[2][1],
+ xyzMatrix.vals[0][2],
+ xyzMatrix.vals[1][2],
+ xyzMatrix.vals[2][2]
+ };
+ env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
+
+ jobject colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_matchMethodID, xyzArray, params);
+
+ if (colorSpace == nullptr) {
+ // We couldn't find an exact match, let's create a new color space
+ // instance with the 3x3 conversion matrix and transfer function
+ colorSpace = env->NewObject(gColorSpaceRGB_class,
+ gColorSpaceRGB_constructorMethodID,
+ env->NewStringUTF("Unknown"), xyzArray, params);
+ }
+
+ env->DeleteLocalRef(xyzArray);
return colorSpace;
}
@@ -658,6 +671,10 @@ int register_android_graphics_Graphics(JNIEnv* env)
FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
+ gColorSpace_Named_ExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
+ gColorSpace_Named_LinearSRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "LINEAR_SRGB", "Landroid/graphics/ColorSpace$Named;");
gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index dc0d022d94c0..f80651c30d64 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -109,7 +109,13 @@ public:
*/
static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle);
- static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+ /**
+ * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace
+ * and decodeColorType.
+ *
+ * This may create a new object if none of the Named ColorSpaces match.
+ */
+ static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
SkColorType decodeColorType);
/**
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index 2d83ac320733..9efcace06be3 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -506,9 +506,9 @@ static jstring ImageDecoder_nGetMimeType(JNIEnv* env, jobject /*clazz*/, jlong n
static jobject ImageDecoder_nGetColorSpace(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
auto* codec = reinterpret_cast<ImageDecoder*>(nativePtr)->mCodec.get();
- auto colorType = codec->computeOutputColorType(codec->getInfo().colorType());
+ auto colorType = codec->computeOutputColorType(kN32_SkColorType);
sk_sp<SkColorSpace> colorSpace = codec->computeOutputColorSpace(colorType);
- return GraphicsJNI::getColorSpace(env, colorSpace, colorType);
+ return GraphicsJNI::getColorSpace(env, colorSpace.get(), colorType);
}
static const JNINativeMethod gImageDecoderMethods[] = {
diff --git a/core/proto/android/server/connectivity/Android.bp b/core/proto/android/server/connectivity/Android.bp
new file mode 100644
index 000000000000..c0ac2cb8f800
--- /dev/null
+++ b/core/proto/android/server/connectivity/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_library_static {
+ name: "datastallprotosnano",
+ proto: {
+ type: "nano",
+ },
+ srcs: [
+ "data_stall_event.proto",
+ ],
+ sdk_version: "system_current",
+ no_framework_libs: true,
+} \ No newline at end of file
diff --git a/core/res/res/drawable/ic_qs_night_display_on.xml b/core/res/res/drawable/ic_qs_night_display_on.xml
index 35907cc83fe0..a4755ee256e2 100644
--- a/core/res/res/drawable/ic_qs_night_display_on.xml
+++ b/core/res/res/drawable/ic_qs_night_display_on.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2017 The Android Open Source Project
+ 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.
@@ -14,14 +14,13 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <group
- android:translateX="-1.0">
- <path
- android:pathData="M13,12c0,-3.57 2.2,-6.62 5.31,-7.87 0.89,-0.36 0.75,-1.69 -0.19,-1.9 -1.1,-0.24 -2.27,-0.3 -3.48,-0.14 -4.51,0.6 -8.12,4.31 -8.59,8.83C5.43,16.93 10.12,22 16,22c0.73,0 1.43,-0.08 2.12,-0.23 0.95,-0.21 1.1,-1.53 0.2,-1.9A8.471,8.471 0,0 1,13 12z"
- android:fillColor="#FFF"/>
- </group>
-</vector> \ No newline at end of file
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.28,4.81c0,0.16,0.01,0.32,0.02,0.48c0.38,6.58,5.83,12.03,12.41,12.41c0.16,0.01,0.32,0.02,0.47,0.02 c-1.58,1.2-3.53,1.88-5.56,1.88c-0.46,0-0.93-0.03-1.4-0.1c-3.96-0.58-7.13-3.75-7.71-7.71C4.13,9.24,4.8,6.75,6.28,4.81 M8.27,0.6 c-0.08,0-0.17,0.02-0.25,0.07c-3.8,2.2-6.2,6.56-5.49,11.4c0.7,4.82,4.59,8.7,9.4,9.4c0.57,0.08,1.13,0.12,1.69,0.12 c4.15,0,7.78-2.26,9.72-5.62c0.2-0.35-0.07-0.76-0.44-0.76c-0.05,0-0.1,0.01-0.15,0.02c-1.03,0.31-2.12,0.48-3.25,0.48 c-0.22,0-0.44-0.01-0.67-0.02C13.23,15.38,8.62,10.77,8.29,5.17C8.21,3.81,8.38,2.49,8.75,1.26C8.86,0.91,8.59,0.6,8.27,0.6 L8.27,0.6z" />
+</vector>
+
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d14164f69850..dae2692c7722 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3252,7 +3252,7 @@
skinny aspect ratio that is not expected to be widely used. -->
<item name="config_pictureInPictureMinAspectRatio" format="float" type="dimen">0.41841004184</item>
- <!-- The minimum aspect ratio (width/height) that is supported for picture-in-picture. Any
+ <!-- The maximum aspect ratio (width/height) that is supported for picture-in-picture. Any
ratio larger than this is considered to wide and short to be usable. Currently 2.39:1. -->
<item name="config_pictureInPictureMaxAspectRatio" format="float" type="dimen">2.39</item>
@@ -3273,6 +3273,11 @@
-->
<integer name="config_dockedStackDividerSnapMode">0</integer>
+ <!-- The maximum aspect ratio (longerSide/shorterSide) that is treated as close-to-square. If
+ config_forceDefaultOrientation is set to true, the rotation on a close-to-square display
+ will be fixed. -->
+ <item name="config_closeToSquareDisplayMaxAspectRatio" format="float" type="dimen">1.333</item>
+
<!-- List of comma separated package names for which we the system will not show crash, ANR,
etc. dialogs. -->
<string translatable="false" name="config_appsNotReportingCrashes"></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a1bafbf8de69..01abffeed384 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -403,6 +403,7 @@
<java-symbol type="integer" name="config_defaultPictureInPictureGravity" />
<java-symbol type="dimen" name="config_pictureInPictureMinAspectRatio" />
<java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" />
+ <java-symbol type="dimen" name="config_closeToSquareDisplayMaxAspectRatio" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index f325d8943ea3..a97c3fa362eb 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -15,6 +15,7 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_CONTEXT_UPDATED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
@@ -174,7 +175,8 @@ public class ContentCaptureEventTest {
assertThat(event.getIds()).isNull();
assertThat(event.getText()).isNull();
assertThat(event.getViewNode()).isNull();
- final ContentCaptureContext clientContext = event.getClientContext();
+ final ContentCaptureContext clientContext = event.getContentCaptureContext();
+ assertThat(clientContext).isNotNull();
assertThat(clientContext.getAction()).isEqualTo("WHATEVER");
}
@@ -205,9 +207,44 @@ public class ContentCaptureEventTest {
assertThat(event.getIds()).isNull();
assertThat(event.getText()).isNull();
assertThat(event.getViewNode()).isNull();
- assertThat(event.getClientContext()).isNull();
+ assertThat(event.getContentCaptureContext()).isNull();
}
+
+ @Test
+ public void testContextUpdated_directly() {
+ final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_CONTEXT_UPDATED)
+ .setClientContext(mClientContext);
+ assertThat(event).isNotNull();
+ assertContextUpdatedEvent(event);
+ }
+
+ @Test
+ public void testContextUpdated_throughParcel() {
+ final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_CONTEXT_UPDATED)
+ .setClientContext(mClientContext);
+ assertThat(event).isNotNull();
+ final ContentCaptureEvent clone = cloneThroughParcel(event);
+ assertContextUpdatedEvent(clone);
+ }
+
+ private void assertContextUpdatedEvent(ContentCaptureEvent event) {
+ assertThat(event.getType()).isEqualTo(TYPE_CONTEXT_UPDATED);
+ assertThat(event.getEventTime()).isAtLeast(MY_EPOCH);
+ assertThat(event.getSessionId()).isEqualTo("42");
+ assertThat(event.getParentSessionId()).isNull();
+ assertThat(event.getId()).isNull();
+ assertThat(event.getIds()).isNull();
+ assertThat(event.getText()).isNull();
+ assertThat(event.getViewNode()).isNull();
+ final ContentCaptureContext clientContext = event.getContentCaptureContext();
+ assertThat(clientContext).isNotNull();
+ assertThat(clientContext.getAction()).isEqualTo("WHATEVER");
+ }
+
+ // TODO(b/123036895): add test for all events type (right now we're just testing the 3 types
+ // that use logic to write to parcel
+
private ContentCaptureEvent cloneThroughParcel(ContentCaptureEvent event) {
Parcel parcel = Parcel.obtain();
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index 34fdebfdf348..b6717e16256f 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -160,5 +160,10 @@ public class ContentCaptureSessionTest {
public void internalNotifyViewHierarchyEvent(boolean started) {
throw new UnsupportedOperationException("should not have been called");
}
+
+ @Override
+ public void updateContentCaptureContext(ContentCaptureContext context) {
+ throw new UnsupportedOperationException("should not have been called");
+ }
}
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 18f0cae4733c..bdb63643f615 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -891,8 +891,10 @@ public final class Bitmap implements Parcelable {
}
}
+ ColorSpace cs = source.getColorSpace();
+
if (m == null || m.isIdentity()) {
- bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
+ bitmap = createBitmap(null, neww, newh, newConfig, source.hasAlpha(), cs);
paint = null; // not needed
} else {
final boolean transformed = !m.rectStaysRect();
@@ -906,9 +908,14 @@ public final class Bitmap implements Parcelable {
if (transformed) {
if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
transformedConfig = Config.ARGB_8888;
+ if (cs == null) {
+ cs = ColorSpace.get(ColorSpace.Named.SRGB);
+ }
}
}
- bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());
+
+ bitmap = createBitmap(null, neww, newh, transformedConfig,
+ transformed || source.hasAlpha(), cs);
paint = new Paint();
paint.setFilterBitmap(filter);
@@ -917,8 +924,6 @@ public final class Bitmap implements Parcelable {
}
}
- nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr);
-
// The new bitmap was created from a known bitmap source so assume that
// they use the same density
bitmap.mDensity = source.mDensity;
@@ -1000,10 +1005,10 @@ public final class Bitmap implements Parcelable {
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
- * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
- * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
- * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
- * is assumed.
+ * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
+ * and {@link ColorSpace.Named#SRGB sRGB} or
+ * {@link ColorSpace.Named#LINEAR_SRGB Linear sRGB} is provided then the
+ * corresponding extended range variant is assumed.
*
* @throws IllegalArgumentException if the width or height are <= 0, if
* Config is Config.HARDWARE (because hardware bitmaps are always
@@ -1055,10 +1060,10 @@ public final class Bitmap implements Parcelable {
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
- * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
- * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
- * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
- * is assumed.
+ * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
+ * and {@link ColorSpace.Named#SRGB sRGB} or
+ * {@link ColorSpace.Named#LINEAR_SRGB Linear sRGB} is provided then the
+ * corresponding extended range variant is assumed.
*
* @throws IllegalArgumentException if the width or height are <= 0, if
* Config is Config.HARDWARE (because hardware bitmaps are always
@@ -1075,22 +1080,12 @@ public final class Bitmap implements Parcelable {
if (config == Config.HARDWARE) {
throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
}
- if (colorSpace == null) {
+ if (colorSpace == null && config != Config.ALPHA_8) {
throw new IllegalArgumentException("can't create bitmap without a color space");
}
- if (config != Config.ARGB_8888) {
- if (config == Config.RGBA_F16) {
- // FIXME: This should be LINEAR_EXTENDED_SRGB, but that would fail a CTS test. See
- // b/120960866. SRGB matches the old (incorrect) behavior.
- //colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
- colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
- } else {
- colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
- }
- }
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true,
- colorSpace.getNativeInstance());
+ colorSpace == null ? 0 : colorSpace.getNativeInstance());
if (display != null) {
bm.mDensity = display.densityDpi;
@@ -1701,41 +1696,9 @@ public final class Bitmap implements Parcelable {
@Nullable
public final ColorSpace getColorSpace() {
checkRecycled("getColorSpace called on a recycled bitmap");
- // Cache the color space retrieval since it can be fairly expensive
if (mColorSpace == null) {
- if (nativeIsConfigF16(mNativePtr)) {
- // an F16 bitmaps is intended to always be linear extended, but due to
- // inconsistencies in Bitmap.create() functions it is possible to have
- // rendered into a bitmap in non-linear sRGB.
- if (nativeIsSRGB(mNativePtr)) {
- mColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
- } else {
- mColorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
- }
- } else if (nativeIsSRGB(mNativePtr)) {
- mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
- } else if (nativeIsSRGBLinear(mNativePtr)) {
- mColorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB);
- } else {
- float[] xyz = new float[9];
- float[] params = new float[7];
-
- boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params);
- if (hasColorSpace) {
- ColorSpace.Rgb.TransferParameters parameters =
- new ColorSpace.Rgb.TransferParameters(
- params[0], params[1], params[2],
- params[3], params[4], params[5], params[6]);
- ColorSpace cs = ColorSpace.match(xyz, parameters);
- if (cs != null) {
- mColorSpace = cs;
- } else {
- mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters);
- }
- }
- }
+ mColorSpace = nativeComputeColorSpace(mNativePtr);
}
-
return mColorSpace;
}
@@ -1749,6 +1712,9 @@ public final class Bitmap implements Parcelable {
* components min/max values reduce the numerical range compared to the
* previously assigned color space.
*
+ * @throws IllegalArgumentException If the {@code Config} (returned by {@link #getConfig()})
+ * is {@link Config#ALPHA_8}.
+ *
* @param colorSpace to assign to the bitmap
*/
public void setColorSpace(@NonNull ColorSpace colorSpace) {
@@ -1756,29 +1722,47 @@ public final class Bitmap implements Parcelable {
if (colorSpace == null) {
throw new IllegalArgumentException("The colorSpace cannot be set to null");
}
- if (getColorSpace() != null) {
- if (mColorSpace.getComponentCount() != colorSpace.getComponentCount()) {
+
+ if (getConfig() == Config.ALPHA_8) {
+ throw new IllegalArgumentException("Cannot set a ColorSpace on ALPHA_8");
+ }
+
+ // Keep track of the old ColorSpace for comparison, and so we can reset it in case of an
+ // Exception.
+ final ColorSpace oldColorSpace = getColorSpace();
+ nativeSetColorSpace(mNativePtr, colorSpace.getNativeInstance());
+
+ // This will update mColorSpace. It may not be the same as |colorSpace|, e.g. if we
+ // corrected it because the Bitmap is F16.
+ mColorSpace = null;
+ final ColorSpace newColorSpace = getColorSpace();
+
+ try {
+ if (oldColorSpace.getComponentCount() != newColorSpace.getComponentCount()) {
throw new IllegalArgumentException("The new ColorSpace must have the same "
+ "component count as the current ColorSpace");
- }
- for (int i = 0; i < mColorSpace.getComponentCount(); i++) {
- if (mColorSpace.getMinValue(i) < colorSpace.getMinValue(i)) {
- throw new IllegalArgumentException("The new ColorSpace cannot increase the "
- + "minimum value for any of the components compared to the current "
- + "ColorSpace. To perform this type of conversion create a new Bitmap "
- + "in the desired ColorSpace and draw this Bitmap into it.");
- }
- if (mColorSpace.getMaxValue(i) > colorSpace.getMaxValue(i)) {
- throw new IllegalArgumentException("The new ColorSpace cannot decrease the "
- + "maximum value for any of the components compared to the current "
- + "ColorSpace/ To perform this type of conversion create a new Bitmap"
- + "in the desired ColorSpace and draw this Bitmap into it.");
+ } else {
+ for (int i = 0; i < oldColorSpace.getComponentCount(); i++) {
+ if (oldColorSpace.getMinValue(i) < newColorSpace.getMinValue(i)) {
+ throw new IllegalArgumentException("The new ColorSpace cannot increase the "
+ + "minimum value for any of the components compared to the current "
+ + "ColorSpace. To perform this type of conversion create a new "
+ + "Bitmap in the desired ColorSpace and draw this Bitmap into it.");
+ }
+ if (oldColorSpace.getMaxValue(i) > newColorSpace.getMaxValue(i)) {
+ throw new IllegalArgumentException("The new ColorSpace cannot decrease the "
+ + "maximum value for any of the components compared to the current "
+ + "ColorSpace/ To perform this type of conversion create a new "
+ + "Bitmap in the desired ColorSpace and draw this Bitmap into it.");
+ }
}
}
+ } catch (IllegalArgumentException e) {
+ // Undo the change to the ColorSpace.
+ mColorSpace = oldColorSpace;
+ nativeSetColorSpace(mNativePtr, mColorSpace.getNativeInstance());
+ throw e;
}
-
- nativeSetColorSpace(mNativePtr, colorSpace.getNativeInstance());
- mColorSpace = colorSpace;
}
/**
@@ -2197,7 +2181,6 @@ public final class Bitmap implements Parcelable {
private static native void nativeErase(long nativeBitmap, long colorSpacePtr, long color);
private static native int nativeRowBytes(long nativeBitmap);
private static native int nativeConfig(long nativeBitmap);
- private static native boolean nativeIsConfigF16(long nativeBitmap);
private static native int nativeGetPixel(long nativeBitmap, int x, int y);
private static native long nativeGetColor(long nativeBitmap, int x, int y);
@@ -2241,11 +2224,10 @@ public final class Bitmap implements Parcelable {
private static native Bitmap nativeWrapHardwareBufferBitmap(HardwareBuffer buffer,
long nativeColorSpace);
private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
- private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
+ private static native ColorSpace nativeComputeColorSpace(long nativePtr);
private static native void nativeSetColorSpace(long nativePtr, long nativeColorSpace);
private static native boolean nativeIsSRGB(long nativePtr);
private static native boolean nativeIsSRGBLinear(long nativePtr);
- private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap);
private static native void nativeSetImmutable(long nativePtr);
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 7aff0414106a..49c3a3ba68b8 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -151,12 +151,9 @@ public class BitmapFactory {
* the decoder will pick either the color space embedded in the image
* or the color space best suited for the requested image configuration
* (for instance {@link ColorSpace.Named#SRGB sRGB} for
- * the {@link Bitmap.Config#ARGB_8888} configuration).</p>
- *
- * <p>{@link Bitmap.Config#RGBA_F16} always uses the
- * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space).
- * Bitmaps in other configurations without an embedded color space are
- * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
+ * {@link Bitmap.Config#ARGB_8888} configuration and
+ * {@link ColorSpace.Named#EXTENDED_SRGB EXTENDED_SRGB} for
+ * {@link Bitmap.Config#RGBA_F16}).</p>
*
* <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are
* currently supported. An <code>IllegalArgumentException</code> will
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index c9e46942a51a..0d5233880674 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1475,7 +1475,7 @@ public abstract class ColorSpace {
x -> absRcpResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
x -> absResponse(x, 1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4),
-0.799f, 2.399f,
- null, // FIXME: Use SRGB_TRANSFER_PARAMETERS
+ SRGB_TRANSFER_PARAMETERS,
Named.EXTENDED_SRGB.ordinal()
);
sNamedColorSpaces[Named.LINEAR_EXTENDED_SRGB.ordinal()] = new ColorSpace.Rgb(
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 466a5fc2a770..26c5080eead0 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -1556,12 +1556,9 @@ public final class ImageDecoder implements AutoCloseable {
* decoder will pick either the color space embedded in the image or the
* {@link ColorSpace} best suited for the requested image configuration
* (for instance {@link ColorSpace.Named#SRGB sRGB} for the
- * {@link Bitmap.Config#ARGB_8888} configuration).</p>
- *
- * <p>{@link Bitmap.Config#RGBA_F16} always uses the
- * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space.
- * Bitmaps in other configurations without an embedded color space are
- * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
+ * {@link Bitmap.Config#ARGB_8888} configuration and
+ * {@link ColorSpace.Named#EXTENDED_SRGB EXTENDED_SRGB} for
+ * {@link Bitmap.Config#RGBA_F16}).</p>
*
* <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are
* currently supported. An <code>IllegalArgumentException</code> will
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 76c56609ef47..2ffda839c210 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -107,7 +107,7 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTran
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
mRenderThread.requireGlContext();
} else {
- mRenderThread.vulkanManager().initialize();
+ mRenderThread.requireVkContext();
}
if (!image.get()) {
return CopyResult::UnknownError;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 15f53f286261..87cffb52c150 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -120,7 +120,7 @@ bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect
}
DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
- mVkManager.initialize();
+ mRenderThread.requireVkContext();
return new DeferredLayerUpdater(mRenderThread.renderState());
}
@@ -136,8 +136,9 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
setSurfaceColorProperties(colorMode);
if (surface) {
+ mRenderThread.requireVkContext();
mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace,
- mSurfaceColorType);
+ mSurfaceColorType, mRenderThread.getGrContext());
}
return mVkSurface != nullptr;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 3904ed20fd77..fc63819120d6 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -173,10 +173,10 @@ void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager();
mRenderState = new RenderState(*this);
- mVkManager = new VulkanManager(*this);
+ mVkManager = new VulkanManager();
mCacheManager = new CacheManager(mDisplayInfo);
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- mVkManager->initialize();
+ requireVkContext();
}
}
@@ -195,8 +195,7 @@ void RenderThread::requireGlContext() {
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
- options.fPreferExternalImagesOverES3 = true;
- options.fDisableDistanceFieldPaths = true;
+ initGrContextOptions(options);
auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
auto size = glesVersion ? strlen(glesVersion) : -1;
cacheManager().configureContext(&options, glesVersion, size);
@@ -205,6 +204,25 @@ void RenderThread::requireGlContext() {
setGrContext(grContext);
}
+void RenderThread::requireVkContext() {
+ if (mVkManager->hasVkContext()) {
+ return;
+ }
+ mVkManager->initialize();
+ GrContextOptions options;
+ initGrContextOptions(options);
+ // TODO: get a string describing the SPIR-V compiler version and use it here
+ cacheManager().configureContext(&options, nullptr, 0);
+ sk_sp<GrContext> grContext = mVkManager->createContext(options);
+ LOG_ALWAYS_FATAL_IF(!grContext.get());
+ setGrContext(grContext);
+}
+
+void RenderThread::initGrContextOptions(GrContextOptions& options) {
+ options.fPreferExternalImagesOverES3 = true;
+ options.fDisableDistanceFieldPaths = true;
+}
+
void RenderThread::destroyRenderingContext() {
mFunctorManager.onContextDestroyed();
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index b18292820c6b..419e7c7a6b51 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -112,6 +112,7 @@ public:
void dumpGraphicsMemory(int fd);
void requireGlContext();
+ void requireVkContext();
void destroyRenderingContext();
/**
@@ -122,6 +123,8 @@ public:
*/
static bool isCurrent();
+ static void initGrContextOptions(GrContextOptions& options);
+
protected:
virtual bool threadLoop() override;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 90397fddf618..1e685abd8afa 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -55,11 +55,7 @@ static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& fe
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
-VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
-
void VulkanManager::destroy() {
- mRenderThread.setGrContext(nullptr);
-
// We don't need to explicitly free the command buffer since it automatically gets freed when we
// delete the VkCommandPool below.
mDummyCB = VK_NULL_HANDLE;
@@ -333,29 +329,10 @@ void VulkanManager::initialize() {
LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
- GrVkExtensions extensions;
- this->setupDevice(extensions, mPhysicalDeviceFeatures2);
+ this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);
mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
- auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
- if (device != VK_NULL_HANDLE) {
- return vkGetDeviceProcAddr(device, proc_name);
- }
- return vkGetInstanceProcAddr(instance, proc_name);
- };
-
- GrVkBackendContext backendContext;
- backendContext.fInstance = mInstance;
- backendContext.fPhysicalDevice = mPhysicalDevice;
- backendContext.fDevice = mDevice;
- backendContext.fQueue = mGraphicsQueue;
- backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
- backendContext.fMaxAPIVersion = mAPIVersion;
- backendContext.fVkExtensions = &extensions;
- backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
- backendContext.fGetProc = std::move(getProc);
-
// create the command pool for the command buffers
if (VK_NULL_HANDLE == mCommandPool) {
VkCommandPoolCreateInfo commandPoolInfo;
@@ -376,22 +353,35 @@ void VulkanManager::initialize() {
}
LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
-
mGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue);
- GrContextOptions options;
- options.fDisableDistanceFieldPaths = true;
- // TODO: get a string describing the SPIR-V compiler version and use it here
- mRenderThread.cacheManager().configureContext(&options, nullptr, 0);
- sk_sp<GrContext> grContext(GrContext::MakeVulkan(backendContext, options));
- LOG_ALWAYS_FATAL_IF(!grContext.get());
- mRenderThread.setGrContext(grContext);
-
if (Properties::enablePartialUpdates && Properties::useBufferAge) {
mSwapBehavior = SwapBehavior::BufferAge;
}
}
+sk_sp<GrContext> VulkanManager::createContext(GrContextOptions options) {
+ auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
+ if (device != VK_NULL_HANDLE) {
+ return vkGetDeviceProcAddr(device, proc_name);
+ }
+ return vkGetInstanceProcAddr(instance, proc_name);
+ };
+
+ GrVkBackendContext backendContext;
+ backendContext.fInstance = mInstance;
+ backendContext.fPhysicalDevice = mPhysicalDevice;
+ backendContext.fDevice = mDevice;
+ backendContext.fQueue = mGraphicsQueue;
+ backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
+ backendContext.fMaxAPIVersion = mAPIVersion;
+ backendContext.fVkExtensions = &mExtensions;
+ backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
+ backendContext.fGetProc = std::move(getProc);
+
+ return GrContext::MakeVulkan(backendContext, options);
+}
+
VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
return VkFunctorInitParams{
.instance = mInstance,
@@ -470,8 +460,9 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
ColorMode colorMode = surface->mColorMode;
sk_sp<SkColorSpace> colorSpace = surface->mColorSpace;
SkColorType colorType = surface->mColorType;
+ GrContext* grContext = surface->mGrContext;
destroySurface(surface);
- *surfaceOut = createSurface(window, colorMode, colorSpace, colorType);
+ *surfaceOut = createSurface(window, colorMode, colorSpace, colorType, grContext);
surface = *surfaceOut;
if (!surface) {
return nullptr;
@@ -650,7 +641,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
- mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin,
+ surface->mGrContext, backendRT, kTopLeft_GrSurfaceOrigin,
surface->mColorType, surface->mColorSpace, &props);
}
@@ -880,15 +871,15 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType) {
- initialize();
-
+ SkColorType surfaceColorType,
+ GrContext* grContext) {
+ LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
if (!window) {
return nullptr;
}
VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace,
- surfaceColorType);
+ surfaceColorType, grContext);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 1fe6c65b35b8..97636865a629 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -22,6 +22,8 @@
#endif
#include <vulkan/vulkan.h>
+#include <GrContextOptions.h>
+#include <vk/GrVkExtensions.h>
#include <SkSurface.h>
#include <ui/Fence.h>
#include <utils/StrongPointer.h>
@@ -39,9 +41,9 @@ class RenderThread;
class VulkanSurface {
public:
VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace,
- SkColorType colorType)
+ SkColorType colorType, GrContext* grContext)
: mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace),
- mColorType(colorType) {}
+ mColorType(colorType), mGrContext(grContext) {}
sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
@@ -93,6 +95,7 @@ private:
SkColorType mColorType;
VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
SkMatrix mPreTransform;
+ GrContext* mGrContext;
};
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -100,6 +103,9 @@ private:
// windowing contexts. The VulkanManager must be initialized before use.
class VulkanManager {
public:
+ explicit VulkanManager() {}
+ ~VulkanManager() { destroy(); }
+
// Sets up the vulkan context that is shared amonst all clients of the VulkanManager. This must
// be call once before use of the VulkanManager. Multiple calls after the first will simiply
// return.
@@ -112,7 +118,8 @@ public:
// VulkanSurface object which is returned.
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType);
+ SkColorType surfaceColorType,
+ GrContext* grContext);
// Destroy the VulkanSurface and all associated vulkan objects.
void destroySurface(VulkanSurface* surface);
@@ -143,12 +150,9 @@ public:
// Returned pointers are owned by VulkanManager.
VkFunctorInitParams getVkFunctorInitParams() const;
-private:
- friend class RenderThread;
-
- explicit VulkanManager(RenderThread& thread);
- ~VulkanManager() { destroy(); }
+ sk_sp<GrContext> createContext(GrContextOptions options);
+private:
// Sets up the VkInstance and VkDevice objects. Also fills out the passed in
// VkPhysicalDeviceFeatures struct.
void setupDevice(GrVkExtensions&, VkPhysicalDeviceFeatures2&);
@@ -231,8 +235,6 @@ private:
VkPtr<PFN_vkWaitForFences> mWaitForFences;
VkPtr<PFN_vkResetFences> mResetFences;
- RenderThread& mRenderThread;
-
VkInstance mInstance = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
VkDevice mDevice = VK_NULL_HANDLE;
@@ -256,6 +258,7 @@ private:
BufferAge,
};
SwapBehavior mSwapBehavior = SwapBehavior::Discard;
+ GrVkExtensions mExtensions;
};
} /* namespace renderthread */
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index a9f651d38a06..e8ba15fe92af 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -100,7 +100,7 @@ void TestUtils::TestTask::run() {
// RenderState only valid once RenderThread is running, so queried here
renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance();
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- renderThread.vulkanManager().initialize();
+ renderThread.requireVkContext();
} else {
renderThread.requireGlContext();
}
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index d742cc34b57e..733b866d9c4c 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -115,10 +115,14 @@ PointerController::~PointerController() {
mLocked.pointerSprite.clear();
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- delete mLocked.spots.itemAt(i);
+ for (auto& it : mLocked.spotsByDisplay) {
+ const std::vector<Spot*>& spots = it.second;
+ size_t numSpots = spots.size();
+ for (size_t i = 0; i < numSpots; i++) {
+ delete spots[i];
+ }
}
- mLocked.spots.clear();
+ mLocked.spotsByDisplay.clear();
mLocked.recycledSprites.clear();
}
@@ -271,22 +275,30 @@ void PointerController::setPresentation(Presentation presentation) {
}
void PointerController::setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
+ const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId) {
#if DEBUG_POINTER_UPDATES
ALOGD("setSpots: idBits=%08x", spotIdBits.value);
for (BitSet32 idBits(spotIdBits); !idBits.isEmpty(); ) {
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
const PointerCoords& c = spotCoords[spotIdToIndex[id]];
- ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f", id,
+ ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id,
c.getAxisValue(AMOTION_EVENT_AXIS_X),
c.getAxisValue(AMOTION_EVENT_AXIS_Y),
- c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+ c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
+ displayId);
}
#endif
AutoMutex _l(mLock);
+ std::vector<Spot*> newSpots;
+ std::map<int32_t, std::vector<Spot*>>::const_iterator iter =
+ mLocked.spotsByDisplay.find(displayId);
+ if (iter != mLocked.spotsByDisplay.end()) {
+ newSpots = iter->second;
+ }
+
mSpriteController->openTransaction();
// Add or move spots for fingers that are down.
@@ -298,17 +310,17 @@ void PointerController::setSpots(const PointerCoords* spotCoords,
float x = c.getAxisValue(AMOTION_EVENT_AXIS_X);
float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
- Spot* spot = getSpotLocked(id);
+ Spot* spot = getSpot(id, newSpots);
if (!spot) {
- spot = createAndAddSpotLocked(id);
+ spot = createAndAddSpotLocked(id, newSpots);
}
- spot->updateSprite(&icon, x, y);
+ spot->updateSprite(&icon, x, y, displayId);
}
// Remove spots for fingers that went up.
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
+ for (size_t i = 0; i < newSpots.size(); i++) {
+ Spot* spot = newSpots[i];
if (spot->id != Spot::INVALID_ID
&& !spotIdBits.hasBit(spot->id)) {
fadeOutAndReleaseSpotLocked(spot);
@@ -316,6 +328,7 @@ void PointerController::setSpots(const PointerCoords* spotCoords,
}
mSpriteController->closeTransaction();
+ mLocked.spotsByDisplay[displayId] = newSpots;
}
void PointerController::clearSpots() {
@@ -539,21 +552,33 @@ bool PointerController::doFadingAnimationLocked(nsecs_t timestamp) {
}
// Animate spots that are fading out and being removed.
- for (size_t i = 0; i < mLocked.spots.size();) {
- Spot* spot = mLocked.spots.itemAt(i);
- if (spot->id == Spot::INVALID_ID) {
- spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
- if (spot->alpha <= 0) {
- mLocked.spots.removeAt(i);
- releaseSpotLocked(spot);
- continue;
- } else {
- spot->sprite->setAlpha(spot->alpha);
- keepAnimating = true;
+ for(auto it = mLocked.spotsByDisplay.begin(); it != mLocked.spotsByDisplay.end();) {
+ std::vector<Spot*>& spots = it->second;
+ size_t numSpots = spots.size();
+ for (size_t i = 0; i < numSpots;) {
+ Spot* spot = spots[i];
+ if (spot->id == Spot::INVALID_ID) {
+ spot->alpha -= float(frameDelay) / SPOT_FADE_DURATION;
+ if (spot->alpha <= 0) {
+ spots.erase(spots.begin() + i);
+ releaseSpotLocked(spot);
+ numSpots--;
+ continue;
+ } else {
+ spot->sprite->setAlpha(spot->alpha);
+ keepAnimating = true;
+ }
}
+ ++i;
+ }
+
+ if (spots.size() == 0) {
+ it = mLocked.spotsByDisplay.erase(it);
+ } else {
+ ++it;
}
- ++i;
}
+
return keepAnimating;
}
@@ -655,47 +680,49 @@ void PointerController::updatePointerLocked() REQUIRES(mLock) {
mSpriteController->closeTransaction();
}
-PointerController::Spot* PointerController::getSpotLocked(uint32_t id) {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
+PointerController::Spot* PointerController::getSpot(uint32_t id, const std::vector<Spot*>& spots) {
+ for (size_t i = 0; i < spots.size(); i++) {
+ Spot* spot = spots[i];
if (spot->id == id) {
return spot;
}
}
- return NULL;
+
+ return nullptr;
}
-PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id) {
+PointerController::Spot* PointerController::createAndAddSpotLocked(uint32_t id,
+ std::vector<Spot*>& spots) {
// Remove spots until we have fewer than MAX_SPOTS remaining.
- while (mLocked.spots.size() >= MAX_SPOTS) {
- Spot* spot = removeFirstFadingSpotLocked();
+ while (spots.size() >= MAX_SPOTS) {
+ Spot* spot = removeFirstFadingSpotLocked(spots);
if (!spot) {
- spot = mLocked.spots.itemAt(0);
- mLocked.spots.removeAt(0);
+ spot = spots[0];
+ spots.erase(spots.begin());
}
releaseSpotLocked(spot);
}
// Obtain a sprite from the recycled pool.
sp<Sprite> sprite;
- if (! mLocked.recycledSprites.isEmpty()) {
- sprite = mLocked.recycledSprites.top();
- mLocked.recycledSprites.pop();
+ if (! mLocked.recycledSprites.empty()) {
+ sprite = mLocked.recycledSprites.back();
+ mLocked.recycledSprites.pop_back();
} else {
sprite = mSpriteController->createSprite();
}
// Return the new spot.
Spot* spot = new Spot(id, sprite);
- mLocked.spots.push(spot);
+ spots.push_back(spot);
return spot;
}
-PointerController::Spot* PointerController::removeFirstFadingSpotLocked() {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
+PointerController::Spot* PointerController::removeFirstFadingSpotLocked(std::vector<Spot*>& spots) {
+ for (size_t i = 0; i < spots.size(); i++) {
+ Spot* spot = spots[i];
if (spot->id == Spot::INVALID_ID) {
- mLocked.spots.removeAt(i);
+ spots.erase(spots.begin() + i);
return spot;
}
}
@@ -706,7 +733,7 @@ void PointerController::releaseSpotLocked(Spot* spot) {
spot->sprite->clearIcon();
if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
- mLocked.recycledSprites.push(spot->sprite);
+ mLocked.recycledSprites.push_back(spot->sprite);
}
delete spot;
@@ -720,9 +747,13 @@ void PointerController::fadeOutAndReleaseSpotLocked(Spot* spot) {
}
void PointerController::fadeOutAndReleaseAllSpotsLocked() {
- for (size_t i = 0; i < mLocked.spots.size(); i++) {
- Spot* spot = mLocked.spots.itemAt(i);
- fadeOutAndReleaseSpotLocked(spot);
+ for (auto& it : mLocked.spotsByDisplay) {
+ const std::vector<Spot*>& spots = it.second;
+ size_t numSpots = spots.size();
+ for (size_t i = 0; i < numSpots; i++) {
+ Spot* spot = spots[i];
+ fadeOutAndReleaseSpotLocked(spot);
+ }
}
}
@@ -743,12 +774,13 @@ void PointerController::loadResourcesLocked() REQUIRES(mLock) {
// --- PointerController::Spot ---
-void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y) {
+void PointerController::Spot::updateSprite(const SpriteIcon* icon, float x, float y,
+ int32_t displayId) {
sprite->setLayer(Sprite::BASE_LAYER_SPOT + id);
sprite->setAlpha(alpha);
sprite->setTransformationMatrix(SpriteTransformationMatrix(scale, 0.0f, 0.0f, scale));
sprite->setPosition(x, y);
-
+ sprite->setDisplayId(displayId);
this->x = x;
this->y = y;
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index be057867890d..52305b8244a6 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -103,7 +103,7 @@ public:
virtual void setPresentation(Presentation presentation);
virtual void setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
+ const uint32_t* spotIdToIndex, BitSet32 spotIdBits, int32_t displayId);
virtual void clearSpots();
void updatePointerIcon(int32_t iconId);
@@ -133,7 +133,7 @@ private:
: id(id), sprite(sprite), alpha(1.0f), scale(1.0f),
x(0.0f), y(0.0f), lastIcon(NULL) { }
- void updateSprite(const SpriteIcon* icon, float x, float y);
+ void updateSprite(const SpriteIcon* icon, float x, float y, int32_t displayId);
private:
const SpriteIcon* lastIcon;
@@ -180,8 +180,8 @@ private:
int32_t buttonState;
- Vector<Spot*> spots;
- Vector<sp<Sprite> > recycledSprites;
+ std::map<int32_t /* displayId */, std::vector<Spot*>> spotsByDisplay;
+ std::vector<sp<Sprite> > recycledSprites;
} mLocked GUARDED_BY(mLock);
bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
@@ -200,9 +200,9 @@ private:
void removeInactivityTimeoutLocked();
void updatePointerLocked();
- Spot* getSpotLocked(uint32_t id);
- Spot* createAndAddSpotLocked(uint32_t id);
- Spot* removeFirstFadingSpotLocked();
+ Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots);
+ Spot* createAndAddSpotLocked(uint32_t id, std::vector<Spot*>& spots);
+ Spot* removeFirstFadingSpotLocked(std::vector<Spot*>& spots);
void releaseSpotLocked(Spot* spot);
void fadeOutAndReleaseSpotLocked(Spot* spot);
void fadeOutAndReleaseAllSpotsLocked();
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 0caa0c5b377a..b3953fddb622 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -184,8 +184,7 @@ public final class LocationRequest implements Parcelable {
* @return a new location request
*/
public static LocationRequest create() {
- LocationRequest request = new LocationRequest();
- return request;
+ return new LocationRequest();
}
/** @hide */
@@ -230,12 +229,10 @@ public final class LocationRequest implements Parcelable {
quality = ACCURACY_FINE;
break;
default: {
- switch (criteria.getPowerRequirement()) {
- case Criteria.POWER_HIGH:
- quality = POWER_HIGH;
- break;
- default:
- quality = POWER_LOW;
+ if (criteria.getPowerRequirement() == Criteria.POWER_HIGH) {
+ quality = POWER_HIGH;
+ } else {
+ quality = POWER_LOW;
}
}
}
@@ -288,7 +285,7 @@ public final class LocationRequest implements Parcelable {
*
* @param quality an accuracy or power constant
* @return the same object, so that setters can be chained
- * @throws InvalidArgumentException if the quality constant is not valid
+ * @throws IllegalArgumentException if the quality constant is not valid
*/
public LocationRequest setQuality(int quality) {
checkQuality(quality);
@@ -331,7 +328,7 @@ public final class LocationRequest implements Parcelable {
*
* @param millis desired interval in millisecond, inexact
* @return the same object, so that setters can be chained
- * @throws InvalidArgumentException if the interval is less than zero
+ * @throws IllegalArgumentException if the interval is less than zero
*/
public LocationRequest setInterval(long millis) {
checkInterval(millis);
@@ -433,7 +430,7 @@ public final class LocationRequest implements Parcelable {
*
* @param millis fastest interval for updates in milliseconds, exact
* @return the same object, so that setters can be chained
- * @throws InvalidArgumentException if the interval is less than zero
+ * @throws IllegalArgumentException if the interval is less than zero
*/
public LocationRequest setFastestInterval(long millis) {
checkInterval(millis);
@@ -528,7 +525,7 @@ public final class LocationRequest implements Parcelable {
*
* @param numUpdates the number of location updates requested
* @return the same object, so that setters can be chained
- * @throws InvalidArgumentException if numUpdates is 0 or less
+ * @throws IllegalArgumentException if numUpdates is 0 or less
*/
public LocationRequest setNumUpdates(int numUpdates) {
if (numUpdates <= 0) {
@@ -668,7 +665,7 @@ public final class LocationRequest implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private static void checkProvider(String name) {
if (name == null) {
- throw new IllegalArgumentException("invalid provider: " + name);
+ throw new IllegalArgumentException("invalid provider: null");
}
}
@@ -758,9 +755,11 @@ public final class LocationRequest implements Parcelable {
if (mNumUpdates != Integer.MAX_VALUE) {
s.append(" num=").append(mNumUpdates);
}
- s.append(" lowPowerMode=").append(mLowPowerMode);
+ if (mLowPowerMode) {
+ s.append(" lowPowerMode");
+ }
if (mLocationSettingsIgnored) {
- s.append(" ignoreSettings");
+ s.append(" locationSettingsIgnored");
}
s.append(']');
return s.toString();
diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index a45c20d9d09d..af8123ac52f4 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -40,7 +40,7 @@ public final class ProviderRequest implements Parcelable {
* restrictions or any other restricting factors and always satisfy this request to the best of
* their ability. This flag should only be used in event of an emergency.
*/
- public boolean forceLocation = false;
+ public boolean locationSettingsIgnored = false;
/**
* Whether provider shall make stronger than normal tradeoffs to substantially restrict power
@@ -70,6 +70,7 @@ public final class ProviderRequest implements Parcelable {
request.reportLocation = in.readInt() == 1;
request.interval = in.readLong();
request.lowPowerMode = in.readBoolean();
+ request.locationSettingsIgnored = in.readBoolean();
int count = in.readInt();
for (int i = 0; i < count; i++) {
request.locationRequests.add(LocationRequest.CREATOR.createFromParcel(in));
@@ -93,6 +94,7 @@ public final class ProviderRequest implements Parcelable {
parcel.writeInt(reportLocation ? 1 : 0);
parcel.writeLong(interval);
parcel.writeBoolean(lowPowerMode);
+ parcel.writeBoolean(locationSettingsIgnored);
parcel.writeInt(locationRequests.size());
for (LocationRequest request : locationRequests) {
request.writeToParcel(parcel, flags);
@@ -107,7 +109,12 @@ public final class ProviderRequest implements Parcelable {
s.append("ON");
s.append(" interval=");
TimeUtils.formatDuration(interval, s);
- s.append(" lowPowerMode=" + lowPowerMode);
+ if (lowPowerMode) {
+ s.append(" lowPowerMode");
+ }
+ if (locationSettingsIgnored) {
+ s.append(" locationSettingsIgnored");
+ }
} else {
s.append("OFF");
}
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 67d64965ac96..dbb581fe54b2 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -31,6 +31,7 @@ package com.android.location.provider {
method public long getInterval();
method public int getQuality();
method public float getSmallestDisplacement();
+ method public boolean isLocationSettingsIgnored();
field public static final int ACCURACY_BLOCK = 102; // 0x66
field public static final int ACCURACY_CITY = 104; // 0x68
field public static final int ACCURACY_FINE = 100; // 0x64
@@ -44,10 +45,10 @@ package com.android.location.provider {
}
public final class ProviderRequestUnbundled {
- method public boolean getForceLocation();
method public long getInterval();
method public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests();
method public boolean getReportLocation();
+ method public boolean isLocationSettingsIgnored();
}
}
diff --git a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
index 41fd769b5abd..2511c39caf5c 100644
--- a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java
@@ -121,6 +121,15 @@ public final class LocationRequestUnbundled {
return delegate.getSmallestDisplacement();
}
+ /**
+ * Returns true if location settings will be ignored in order to satisfy this request.
+ *
+ * @return true if location settings will be ignored in order to satisfy this request
+ */
+ public boolean isLocationSettingsIgnored() {
+ return delegate.isLocationSettingsIgnored();
+ }
+
@Override
public String toString() {
return delegate.toString();
diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
index b825b58cd3e9..febbf1b23e0c 100644
--- a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
+++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java
@@ -46,15 +46,15 @@ public final class ProviderRequestUnbundled {
return mRequest.interval;
}
- public boolean getForceLocation() {
- return mRequest.forceLocation;
+ public boolean isLocationSettingsIgnored() {
+ return mRequest.locationSettingsIgnored;
}
/**
* Never null.
*/
public List<LocationRequestUnbundled> getLocationRequests() {
- List<LocationRequestUnbundled> result = new ArrayList<LocationRequestUnbundled>(
+ List<LocationRequestUnbundled> result = new ArrayList<>(
mRequest.locationRequests.size());
for (LocationRequest r : mRequest.locationRequests) {
result.add(new LocationRequestUnbundled(r));
diff --git a/media/apex/java/android/media/MediaController2.java b/media/apex/java/android/media/MediaController2.java
index 887b4475a4d1..e85d99774986 100644
--- a/media/apex/java/android/media/MediaController2.java
+++ b/media/apex/java/android/media/MediaController2.java
@@ -425,7 +425,7 @@ public class MediaController2 implements AutoCloseable {
public void onDisconnected(@NonNull MediaController2 controller) {}
/**
- * Called when the playback of the session's playback activeness is changed.
+ * Called when the session's playback activeness is changed.
*
* @param controller the controller for this event
* @param playbackActive {@code true} if the session's playback is active.
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index fb18c3b67480..e4d356b48f6d 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1180,13 +1180,8 @@ public class MediaPlayer extends PlayerBase
}
final File file = new File(path);
- if (file.exists()) {
- FileInputStream is = new FileInputStream(file);
- FileDescriptor fd = is.getFD();
- setDataSource(fd);
- is.close();
- } else {
- throw new IOException("setDataSource failed.");
+ try (FileInputStream is = new FileInputStream(file)) {
+ setDataSource(is.getFD());
}
}
@@ -2868,15 +2863,9 @@ public class MediaPlayer extends PlayerBase
throw new IllegalArgumentException(msg);
}
- File file = new File(path);
- if (file.exists()) {
- FileInputStream is = new FileInputStream(file);
- FileDescriptor fd = is.getFD();
- addTimedTextSource(fd, mimeType);
- is.close();
- } else {
- // We do not support the case where the path is not a file.
- throw new IOException(path);
+ final File file = new File(path);
+ try (FileInputStream is = new FileInputStream(file)) {
+ addTimedTextSource(is.getFD(), mimeType);
}
}
diff --git a/media/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
index 64d283f168e1..40c716607697 100644
--- a/media/java/android/media/session/ControllerLink.java
+++ b/media/java/android/media/session/ControllerLink.java
@@ -493,6 +493,22 @@ public final class ControllerLink implements Parcelable {
}
/**
+ * Tell system that a controller requests changing the playback speed.
+ *
+ * @param packageName the package name of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param speed the playback speed
+ */
+ void setPlaybackSpeed(@NonNull String packageName, @NonNull ControllerCallbackLink caller,
+ float speed) {
+ try {
+ mISessionController.setPlaybackSpeed(packageName, caller, speed);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Tell system that a controller sends a custom action.
*
* @param packageName the package name of the controller
@@ -759,6 +775,11 @@ public final class ControllerLink implements Parcelable {
@NonNull Rating rating) {
}
+ /** Stub method for ISessionController.setPlaybackSpeed */
+ public void setPlaybackSpeed(@NonNull String packageName,
+ @NonNull ControllerCallbackLink caller, float speed) {
+ }
+
/** Stub method for ISessionController.sendCustomAction */
public void sendCustomAction(@NonNull String packageName,
@NonNull ControllerCallbackLink caller, @NonNull String action,
@@ -953,6 +974,12 @@ public final class ControllerLink implements Parcelable {
}
@Override
+ public void setPlaybackSpeed(String packageName, ControllerCallbackLink caller,
+ float speed) {
+ mControllerStub.setPlaybackSpeed(packageName, caller, speed);
+ }
+
+ @Override
public void sendCustomAction(String packageName, ControllerCallbackLink caller,
String action, Bundle args) {
mControllerStub.sendCustomAction(packageName, caller, action, args);
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 9b86bfced340..cd33c044d142 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -60,6 +60,8 @@ oneway interface ISessionCallback {
long pos);
void notifyRate(String packageName, int pid, int uid, in ControllerCallbackLink caller,
in Rating rating);
+ void notifySetPlaybackSpeed(String packageName, int pid, int uid,
+ in ControllerCallbackLink caller, float speed);
void notifyCustomAction(String packageName, int pid, int uid, in ControllerCallbackLink caller,
String action, in Bundle args);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index e697c65e11c0..3e7b4fbdebd3 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -76,6 +76,7 @@ interface ISessionController {
void rewind(String packageName, in ControllerCallbackLink caller);
void seekTo(String packageName, in ControllerCallbackLink caller, long pos);
void rate(String packageName, in ControllerCallbackLink caller, in Rating rating);
+ void setPlaybackSpeed(String packageName, in ControllerCallbackLink caller, float speed);
void sendCustomAction(String packageName, in ControllerCallbackLink caller,
String action, in Bundle args);
MediaMetadata getMetadata();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 6e2c8c51c734..9e4199cba47a 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -865,6 +865,19 @@ public final class MediaController {
}
/**
+ * Set the playback speed.
+ *
+ * @param speed The playback speed
+ */
+ public void setPlaybackSpeed(float speed) {
+ try {
+ mSessionBinder.setPlaybackSpeed(mContext.getPackageName(), mCbStub, speed);
+ } catch (RuntimeException e) {
+ Log.wtf(TAG, "Error calling setPlaybackSpeed.", e);
+ }
+ }
+
+ /**
* Send a custom action back for the {@link MediaSession} to perform.
*
* @param customAction The action to perform.
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 1b9ebdafd328..8ab893b03a62 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -681,6 +681,19 @@ public final class MediaSession {
}
/**
+ * Override to handle the playback speed change.
+ * To update the new playback speed, create a new {@link PlaybackState} by using {@link
+ * PlaybackState.Builder#setState(int, long, float)}, and set it with
+ * {@link #setPlaybackState(PlaybackState)}.
+ *
+ * @param speed the playback speed
+ * @see #setPlaybackState(PlaybackState)
+ * @see PlaybackState.Builder#setState(int, long, float)
+ */
+ public void onSetPlaybackSpeed(float speed) {
+ }
+
+ /**
* Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be
* performed.
*
diff --git a/media/java/android/media/session/MediaSessionEngine.java b/media/java/android/media/session/MediaSessionEngine.java
index e19bdbcf923e..266bf3226c49 100644
--- a/media/java/android/media/session/MediaSessionEngine.java
+++ b/media/java/android/media/session/MediaSessionEngine.java
@@ -538,6 +538,10 @@ public final class MediaSessionEngine implements AutoCloseable {
postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null);
}
+ void dispatchSetPlaybackSpeed(RemoteUserInfo caller, float speed) {
+ postToCallback(caller, CallbackMessageHandler.MSG_SET_PLAYBACK_SPEED, speed, null);
+ }
+
void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
}
@@ -871,6 +875,17 @@ public final class MediaSessionEngine implements AutoCloseable {
}
/**
+ * Override to handle the playback speed change.
+ *
+ * @param speed the playback speed
+ */
+ public void onSetPlaybackSpeed(float speed) {
+ if (mCallback != null) {
+ mCallback.onSetPlaybackSpeed(speed);
+ }
+ }
+
+ /**
* Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be
* performed.
*
@@ -1092,10 +1107,11 @@ public final class MediaSessionEngine implements AutoCloseable {
private static final int MSG_REWIND = 17;
private static final int MSG_SEEK_TO = 18;
private static final int MSG_RATE = 19;
- private static final int MSG_CUSTOM_ACTION = 20;
- private static final int MSG_ADJUST_VOLUME = 21;
- private static final int MSG_SET_VOLUME = 22;
- private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;
+ private static final int MSG_SET_PLAYBACK_SPEED = 20;
+ private static final int MSG_CUSTOM_ACTION = 21;
+ private static final int MSG_ADJUST_VOLUME = 22;
+ private static final int MSG_SET_VOLUME = 23;
+ private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 24;
@SuppressWarnings("WeakerAccess") /* synthetic access */
CallbackWrapper mCallbackWrapper;
@@ -1186,6 +1202,9 @@ public final class MediaSessionEngine implements AutoCloseable {
case MSG_RATE:
mCallbackWrapper.onSetRating((Rating) obj);
break;
+ case MSG_SET_PLAYBACK_SPEED:
+ mCallbackWrapper.onSetPlaybackSpeed((Float) obj);
+ break;
case MSG_CUSTOM_ACTION:
mCallbackWrapper.onCustomAction((String) obj, msg.getData());
break;
diff --git a/media/java/android/media/session/SessionCallbackLink.java b/media/java/android/media/session/SessionCallbackLink.java
index f59a69d6e157..f9fa45a1b619 100644
--- a/media/java/android/media/session/SessionCallbackLink.java
+++ b/media/java/android/media/session/SessionCallbackLink.java
@@ -462,6 +462,25 @@ public final class SessionCallbackLink implements Parcelable {
}
/**
+ * Notify session that a controller requests changing playback speed.
+ *
+ * @param packageName the package name of the controller
+ * @param pid the pid of the controller
+ * @param uid the uid of the controller
+ * @param caller the {@link ControllerCallbackLink} of the controller
+ * @param speed the playback speed
+ */
+ @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
+ public void notifySetPlaybackSpeed(@NonNull String packageName, int pid, int uid,
+ @NonNull ControllerCallbackLink caller, float speed) {
+ try {
+ mISessionCallback.notifySetPlaybackSpeed(packageName, pid, uid, caller, speed);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Notify session that a controller sends a custom action.
*
* @param packageName the package name of the controller
@@ -871,6 +890,23 @@ public final class SessionCallbackLink implements Parcelable {
}
}
+ @Override
+ public void notifySetPlaybackSpeed(String packageName, int pid, int uid,
+ ControllerCallbackLink caller, float speed) {
+ ensureMediaControlPermission();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ MediaSessionEngine sessionImpl = mSessionImpl.get();
+ if (sessionImpl != null) {
+ sessionImpl.dispatchSetPlaybackSpeed(
+ createRemoteUserInfo(packageName, pid, uid), speed);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void notifyCustomAction(String packageName, int pid, int uid,
ControllerCallbackLink caller, String action, Bundle args) {
ensureMediaControlPermission();
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index ce627ce47717..a288d010e59b 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -175,6 +175,7 @@ public class CaptivePortalLoginActivity extends Activity {
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
+ webSettings.setDomStorageEnabled(true);
mWebViewClient = new MyWebViewClient();
webview.setWebViewClient(mWebViewClient);
webview.setWebChromeClient(new MyWebChromeClient());
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index f36b4aa87636..55c9361ce6c4 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -106,6 +106,7 @@ public class CaptivePortalLoginActivity extends Activity {
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
+ webSettings.setDomStorageEnabled(true);
mWebViewClient = new MyWebViewClient();
mWebView.setWebViewClient(mWebViewClient);
mWebView.setWebChromeClient(new MyWebChromeClient());
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index e4d35915c77c..860ebfbf6da7 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -31,6 +31,7 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.NETWORK_STACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<application
android:label="NetworkStack"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 9e5991298834..b1f6d246563e 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -46,6 +46,7 @@ import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.ConditionVariable;
+import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -380,6 +381,13 @@ public class IpClient extends StateMachine {
public InterfaceParams getInterfaceParams(String ifname) {
return InterfaceParams.getByName(ifname);
}
+
+ /**
+ * Get a INetd connector.
+ */
+ public INetd getNetd(Context context) {
+ return INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE));
+ }
}
public IpClient(Context context, String ifName, IIpClientCallbacks callback,
@@ -413,7 +421,7 @@ public class IpClient extends StateMachine {
// TODO: Consider creating, constructing, and passing in some kind of
// InterfaceController.Dependencies class.
- mNetd = mContext.getSystemService(INetd.class);
+ mNetd = deps.getNetd(mContext);
mInterfaceCtrl = new InterfaceController(mInterfaceName, mNetd, mLog);
mLinkObserver = new IpClientLinkObserver(
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index cedcb84e9d08..c6a207f26577 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -114,7 +114,8 @@ public class NetworkStackService extends Service {
NetworkStackConnector(Context context) {
mContext = context;
- mNetd = (INetd) context.getSystemService(Context.NETD_SERVICE);
+ mNetd = INetd.Stub.asInterface(
+ (IBinder) context.getSystemService(Context.NETD_SERVICE));
mObserverRegistry = new NetworkObserverRegistry();
mCm = context.getSystemService(ConnectivityManager.class);
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 2e72d8296a37..b9e901b5c5e3 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -67,15 +67,9 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.telephony.CellIdentityCdma;
-import android.telephony.CellIdentityGsm;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityWcdma;
-import android.telephony.CellInfo;
-import android.telephony.CellInfoCdma;
-import android.telephony.CellInfoGsm;
-import android.telephony.CellInfoLte;
-import android.telephony.CellInfoWcdma;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationState;
+import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -1312,6 +1306,7 @@ public class NetworkMonitor extends StateMachine {
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
+ urlConnection.setRequestProperty("Connection", "close");
urlConnection.setUseCaches(false);
if (mCaptivePortalUserAgent != null) {
urlConnection.setRequestProperty("User-Agent", mCaptivePortalUserAgent);
@@ -1485,10 +1480,6 @@ public class NetworkMonitor extends StateMachine {
*/
private void sendNetworkConditionsBroadcast(boolean responseReceived, boolean isCaptivePortal,
long requestTimestampMs, long responseTimestampMs) {
- if (!mWifiManager.isScanAlwaysAvailable()) {
- return;
- }
-
if (!mSystemReady) {
return;
}
@@ -1496,6 +1487,10 @@ public class NetworkMonitor extends StateMachine {
Intent latencyBroadcast =
new Intent(NetworkMonitorUtils.ACTION_NETWORK_CONDITIONS_MEASURED);
if (mNetworkCapabilities.hasTransport(TRANSPORT_WIFI)) {
+ if (!mWifiManager.isScanAlwaysAvailable()) {
+ return;
+ }
+
WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
if (currentWifiInfo != null) {
// NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
@@ -1515,39 +1510,21 @@ public class NetworkMonitor extends StateMachine {
}
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_WIFI);
} else if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ // TODO(b/123893112): Support multi-sim.
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_NETWORK_TYPE,
mTelephonyManager.getNetworkType());
- List<CellInfo> info = mTelephonyManager.getAllCellInfo();
- if (info == null) return;
- int numRegisteredCellInfo = 0;
- for (CellInfo cellInfo : info) {
- if (cellInfo.isRegistered()) {
- numRegisteredCellInfo++;
- if (numRegisteredCellInfo > 1) {
- if (VDBG) {
- logw("more than one registered CellInfo."
- + " Can't tell which is active. Bailing.");
- }
- return;
- }
- if (cellInfo instanceof CellInfoCdma) {
- CellIdentityCdma cellId = ((CellInfoCdma) cellInfo).getCellIdentity();
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
- } else if (cellInfo instanceof CellInfoGsm) {
- CellIdentityGsm cellId = ((CellInfoGsm) cellInfo).getCellIdentity();
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
- } else if (cellInfo instanceof CellInfoLte) {
- CellIdentityLte cellId = ((CellInfoLte) cellInfo).getCellIdentity();
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
- } else if (cellInfo instanceof CellInfoWcdma) {
- CellIdentityWcdma cellId = ((CellInfoWcdma) cellInfo).getCellIdentity();
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CELL_ID, cellId);
- } else {
- if (VDBG) logw("Registered cellinfo is unrecognized");
- return;
- }
- }
+ final ServiceState dataSs = mTelephonyManager.getServiceState();
+ if (dataSs == null) {
+ logw("failed to retrieve ServiceState");
+ return;
}
+ // See if the data sub is registered for PS services on cell.
+ final NetworkRegistrationState nrs = dataSs.getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS,
+ AccessNetworkConstants.TransportType.WWAN);
+ latencyBroadcast.putExtra(
+ NetworkMonitorUtils.EXTRA_CELL_ID,
+ nrs == null ? null : nrs.getCellIdentity());
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_MOBILE);
} else {
return;
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 7e57d1eb00b0..aaaff0279fed 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -104,8 +104,8 @@ public class IpClientTest {
when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm);
when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm);
- when(mContext.getSystemService(INetd.class)).thenReturn(mNetd);
when(mContext.getResources()).thenReturn(mResources);
+ when(mDependencies.getNetd(any())).thenReturn(mNetd);
when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
.thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml
index 96045120fec4..013d2d004471 100644
--- a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml
+++ b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml
@@ -23,7 +23,7 @@
android:layout_marginEnd="16dp"
android:gravity="center"
android:clickable="true"
- android:background="?android:attr/selectableItemBackground"
+ android:background="@*android:drawable/btn_borderless_material"
android:orientation="vertical">
<ImageView
diff --git a/packages/SettingsLib/res/drawable/ic_info_outline_24.xml b/packages/SettingsLib/res/drawable/ic_info_outline_24.xml
new file mode 100644
index 000000000000..317e43b95cdd
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_info_outline_24.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
index a106846fac26..2a1281027169 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
@@ -56,7 +56,7 @@ public class FooterPreference extends Preference {
}
private void init() {
- setIcon(com.android.internal.R.drawable.ic_info_outline_24);
+ setIcon(R.drawable.ic_info_outline_24);
setKey(KEY_FOOTER);
setOrder(ORDER_FOOTER);
setSelectable(false);
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index b673e4f3b081..dd124b713a72 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -14,12 +14,19 @@ Copyright (C) 2017 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal" >
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L11,14.41V22h1l5.71-5.71L13.41,12L17.71,7.71z M13,5.83 l1.88,1.88L13,9.59V5.83z M14.88,16.29L13,18.17v-3.76L14.88,16.29z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M 5 10.5 C 5.82842712475 10.5 6.5 11.1715728753 6.5 12 C 6.5 12.8284271247 5.82842712475 13.5 5 13.5 C 4.17157287525 13.5 3.5 12.8284271247 3.5 12 C 3.5 11.1715728753 4.17157287525 10.5 5 10.5 Z" />
<path
- android:pathData="M13.51,12l3.75,-3.74c0.41,-0.41 0.41,-1.07 0,-1.48l-4.47,-4.47 -0.03,-0.03a1.046,1.046 0,0 0,-1.76 0.76v6.44L6.95,5.43c-0.41,-0.41 -1.06,-0.41 -1.47,0s-0.41,1.06 0,1.47l5.09,5.1 -5.09,5.09c-0.41,0.41 -0.41,1.06 0,1.47s1.06,0.41 1.47,0L11,14.51v6.45a1.04,1.04 0,0 0,1.75 0.76l0.05,-0.05 4.46,-4.46c0.41,-0.41 0.41,-1.07 0,-1.48L13.51,12zM12.99,9.67v-4.3l2.15,2.15 -2.15,2.15zM12.99,18.62v-4.3l2.15,2.15 -2.15,2.15zM6.06,13.06c-0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0c0.59,0.59 0.59,1.53 0,2.12zM20.06,10.94c0.59,0.59 0.59,1.54 0,2.12 -0.59,0.59 -1.54,0.59 -2.12,0a1.49,1.49 0,0 1,0 -2.12,1.49 1.49,0 0,1 2.12,0z"
- android:fillColor="#FFFFFFFF" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M 19 10.5 C 19.8284271247 10.5 20.5 11.1715728753 20.5 12 C 20.5 12.8284271247 19.8284271247 13.5 19 13.5 C 18.1715728753 13.5 17.5 12.8284271247 17.5 12 C 17.5 11.1715728753 18.1715728753 10.5 19 10.5 Z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
index 8cc6caa8abc8..220c63ccca6d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_on.xml
@@ -14,12 +14,13 @@ Copyright (C) 2017 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M13.5,12l3.8,-3.7c0.4,-0.4 0.4,-1.1 0,-1.5l-4.5,-4.5c-0.4,-0.4 -1.1,-0.4 -1.5,0.1C11.1,2.5 11,2.8 11,3v6.4L6.9,5.4C6.5,5 5.9,5 5.5,5.4s-0.4,1.1 0,1.5l5.1,5.1l-5.1,5.1c-0.4,0.4 -0.4,1.1 0,1.5s1.1,0.4 1.5,0l4.1,-4V21c0,0.6 0.5,1 1,1c0.3,0 0.5,-0.1 0.7,-0.3l0.1,0l4.5,-4.5c0.4,-0.4 0.4,-1.1 0,-1.5L13.5,12zM13,9.7V5.4l2.1,2.2L13,9.7zM13,18.6v-4.3l2.1,2.2L13,18.6z"/>
+ android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L11,14.41V22h1l5.71-5.71L13.41,12L17.71,7.71z M13,5.83 l1.88,1.88L13,9.59V5.83z M14.88,16.29L13,18.17v-3.76L14.88,16.29z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane.xml b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
index 0a4d7526a55d..f708ed9cb8a6 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2017 The Android Open Source Project
+ 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.
@@ -15,16 +15,12 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="20.5"
- android:viewportHeight="20.5">
- <group
- android:translateX="1.75"
- android:translateY="1.4">
- <path
- android:pathData="M16.01,9.87l-6.24,-3.9v-4.7C9.77,0.57 9.21,0 8.5,0S7.23,0.57 7.23,1.28v4.7L0.99,9.88c-0.37,0.23 -0.6,0.64 -0.6,1.08v0.41c0,0.29 0.29,0.5 0.55,0.41l6.27,-1.97v4.7l-1.37,1.02c-0.21,0.16 -0.34,0.41 -0.34,0.68v0.57c0,0.15 0.12,0.23 0.27,0.2 1.67,-0.47 1.12,-0.31 2.73,-0.78 1.03,0.3 1.7,0.49 2.72,0.78 0.15,0.03 0.27,-0.06 0.27,-0.2v-0.57c0,-0.27 -0.13,-0.52 -0.34,-0.68l-1.37,-1.02v-4.7l6.27,1.97c0.28,0.09 0.55,-0.12 0.55,-0.41v-0.41c0.01,-0.45 -0.23,-0.87 -0.59,-1.09z"
- android:fillColor="#FFF"/>
- </group>
-</vector>
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+<path
+ android:fillColor="#FFFFFF"
+ android:pathData="M21,16v-2l-8-5V3.5C13,2.67,12.33,2,11.5,2S10,2.67,10,3.5V9l-8,5v2l8-2.5V19l-2,1.5V22l3.5-1l3.5,1v-1.5L13,19v-5.5L21,16z" />
+</vector>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
new file mode 100644
index 000000000000..911b661d48eb
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.systemui.globalactions.GlobalActionsGridLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/global_actions_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:theme="@style/qs_theme"
+ android:gravity="top|right"
+ android:clipChildren="false"
+>
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:gravity="top|right"
+ android:padding="0dp"
+ android:orientation="vertical"
+ android:layoutDirection="ltr"
+ android:layout_marginRight="@dimen/global_actions_grid_container_bottom_margin"
+ >
+ <!-- Grid of action items -->
+ <com.android.systemui.globalactions.ListGridLayout
+ android:id="@android:id/list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layoutDirection="ltr"
+ android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:translationZ="@dimen/global_actions_translate"
+ android:paddingLeft="@dimen/global_actions_grid_top_padding"
+ android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingTop="@dimen/global_actions_grid_left_padding"
+ android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:background="?android:attr/colorBackgroundFloating"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="ltr"
+ android:orientation="horizontal"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="ltr"
+ android:orientation="horizontal"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="ltr"
+ android:orientation="horizontal"
+ />
+ </com.android.systemui.globalactions.ListGridLayout>
+
+ <!-- For separated items-->
+ <LinearLayout
+ android:id="@+id/separated_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
+ android:paddingTop="@dimen/global_actions_grid_left_padding"
+ android:paddingLeft="@dimen/global_actions_grid_top_padding"
+ android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:orientation="horizontal"
+ android:layoutDirection="ltr"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:translationZ="@dimen/global_actions_translate"
+ />
+
+ </LinearLayout>
+
+</com.android.systemui.globalactions.GlobalActionsGridLayout>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
new file mode 100644
index 000000000000..669be1b40567
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.systemui.globalactions.GlobalActionsGridLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/global_actions_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:clipToPadding="false"
+ android:theme="@style/qs_theme"
+ android:gravity="top|left"
+ android:clipChildren="false"
+>
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:gravity="bottom|left"
+ android:padding="0dp"
+ android:orientation="vertical"
+ android:layout_marginLeft="@dimen/global_actions_grid_container_bottom_margin"
+ >
+ <!-- For separated items-->
+ <LinearLayout
+ android:id="@+id/separated_button"
+ android:layout_gravity="top|left"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
+ android:paddingTop="@dimen/global_actions_grid_left_padding"
+ android:paddingLeft="@dimen/global_actions_grid_top_padding"
+ android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:orientation="horizontal"
+ android:layoutDirection="rtl"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:translationZ="@dimen/global_actions_translate"
+ />
+
+ <!-- Grid of action items -->
+ <com.android.systemui.globalactions.ListGridLayout
+ android:id="@android:id/list"
+ android:layout_gravity="bottom|left"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:translationZ="@dimen/global_actions_translate"
+ android:paddingLeft="@dimen/global_actions_grid_top_padding"
+ android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingTop="@dimen/global_actions_grid_left_padding"
+ android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:background="?android:attr/colorBackgroundFloating"
+ >
+ <LinearLayout
+ android:layout_gravity="bottom"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="rtl"
+ android:orientation="horizontal"
+ />
+ <LinearLayout
+ android:layout_gravity="bottom"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="rtl"
+ android:orientation="horizontal"
+ />
+ <LinearLayout
+ android:layout_gravity="bottom"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="rtl"
+ android:orientation="horizontal"
+ />
+ </com.android.systemui.globalactions.ListGridLayout>
+ </LinearLayout>
+
+</com.android.systemui.globalactions.GlobalActionsGridLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index e6f2376ae76b..1b56fa089281 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -12,10 +12,11 @@
>
<LinearLayout
- android:layout_height="290dp"
- android:layout_width="412dp"
- android:gravity="bottom"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:gravity="bottom | right"
android:padding="0dp"
+ android:layoutDirection="ltr"
android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
>
<!-- For separated items-->
@@ -34,15 +35,11 @@
android:translationZ="@dimen/global_actions_translate"
/>
- <Space android:layout_width="match_parent" android:layout_height="2dp"
- android:layout_weight="1" />
-
<!-- Grid of action items -->
<com.android.systemui.globalactions.ListGridLayout
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="right"
android:orientation="horizontal"
android:layoutDirection="rtl"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
@@ -56,25 +53,19 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="bottom|right"
android:visibility="gone"
- android:gravity="bottom"
android:orientation="vertical"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="bottom|right"
android:visibility="gone"
- android:gravity="bottom"
android:orientation="vertical"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="bottom|right"
android:visibility="gone"
- android:gravity="bottom"
android:orientation="vertical"
/>
</com.android.systemui.globalactions.ListGridLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
index 0c11cd977256..a8938390690f 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml
@@ -47,6 +47,7 @@
android:gravity="center"
android:textSize="12sp"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:singleLine="true"
/>
<TextView
@@ -57,5 +58,6 @@
android:gravity="center"
android:textColor="?android:attr/textColorTertiary"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:singleLine="true"
/>
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index ce9c637cebf6..3c6f081d0373 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -21,11 +21,13 @@ import com.android.systemui.appops.AppOpsControllerImpl;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
@@ -194,6 +196,12 @@ public abstract class DependencyBinder {
/**
*/
@Binds
+ public abstract StatusBarStateController provideStatusBarStateController(
+ StatusBarStateControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
public abstract StatusBarIconController provideStatusBarIconController(
StatusBarIconControllerImpl controllerImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index e28aa9d369cb..2a1d066d356e 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
-import android.content.res.Configuration;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -59,7 +58,6 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
private int mEndPoint;
private boolean mEdgeBleed;
private boolean mRoundedDivider;
- private int mRotation = ROTATION_NONE;
private boolean mRotatedBackground;
private boolean mSwapOrientation = true;
@@ -89,7 +87,7 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
}
@Override
- public ViewGroup getParentView(boolean separated, int index) {
+ public ViewGroup getParentView(boolean separated, int index, boolean reverse) {
if (separated) {
return getSeparatedView();
} else {
@@ -174,7 +172,6 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
mSeparatedView.setBackground(mSeparatedViewBackground);
updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
mOldHeight = mList.getMeasuredHeight();
- updateRotation();
} else {
return;
}
@@ -188,25 +185,13 @@ public class HardwareUiLayout extends MultiListLayout implements Tunable {
post(() -> updatePosition());
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateRotation();
- }
-
public void setSwapOrientation(boolean swapOrientation) {
mSwapOrientation = swapOrientation;
}
- private void updateRotation() {
- int rotation = RotationUtils.getRotation(getContext());
- if (rotation != mRotation) {
- rotate(mRotation, rotation);
- mRotation = rotation;
- }
- }
-
- private void rotate(int from, int to) {
+ @Override
+ protected void rotate(int from, int to) {
+ super.rotate(from, to);
if (from != ROTATION_NONE && to != ROTATION_NONE) {
// Rather than handling this confusing case, just do 2 rotations.
rotate(from, ROTATION_NONE);
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index 85265f458370..00ff518ce212 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -17,11 +17,14 @@
package com.android.systemui;
import android.content.Context;
+import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import com.android.systemui.util.leak.RotationUtils;
+
/**
* Layout class representing the Global Actions menu which appears when the power button is held.
*/
@@ -32,8 +35,12 @@ public abstract class MultiListLayout extends LinearLayout {
protected int mExpectedSeparatedItemCount;
protected int mExpectedListItemCount;
+ protected int mRotation;
+ protected RotationListener mRotationListener;
+
public MultiListLayout(Context context, AttributeSet attrs) {
super(context, attrs);
+ mRotation = RotationUtils.getRotation(context);
}
protected abstract ViewGroup getSeparatedView();
@@ -50,10 +57,12 @@ public abstract class MultiListLayout extends LinearLayout {
* @param separated Whether or not this index refers to a position in the separated or list
* container.
* @param index The index of the item within the container.
+ * @param reverse If the MultiListLayout contains sub-lists within the list container, reverse
+ * the order that they are filled.
* @return The parent ViewGroup which will be used to contain the specified item
* after it has been added to the layout.
*/
- public abstract ViewGroup getParentView(boolean separated, int index);
+ public abstract ViewGroup getParentView(boolean separated, int index, boolean reverse);
/**
* Sets the divided view, which may have a differently-colored background.
@@ -111,6 +120,26 @@ public abstract class MultiListLayout extends LinearLayout {
setFocusable(true);
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ int newRotation = RotationUtils.getRotation(mContext);
+ if (newRotation != mRotation) {
+ rotate(mRotation, newRotation);
+ mRotation = newRotation;
+ }
+ }
+
+ protected void rotate(int from, int to) {
+ if (mRotationListener != null) {
+ mRotationListener.onRotate(from, to);
+ }
+ }
+
+ public void setRotationListener(RotationListener listener) {
+ mRotationListener = listener;
+ }
+
/**
* Retrieve the MultiListLayout associated with the given view.
*/
@@ -121,4 +150,8 @@ public abstract class MultiListLayout extends LinearLayout {
}
return null;
}
+
+ interface RotationListener {
+ void onRotate(int from, int to);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index d27a90332ac5..6d583df6082b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -42,7 +42,6 @@ import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -154,15 +153,6 @@ public class SystemUIFactory {
return new VolumeDialogComponent(systemUi, context);
}
- /**
- * Provides status bar state controller implementation
- */
- @Singleton
- @Provides
- public StatusBarStateController provideStatusBarStateController(Context context) {
- return new StatusBarStateControllerImpl();
- }
-
@Singleton
@Provides
public NotificationData.KeyguardEnvironment provideKeyguardEnvironment(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 5efdc2f61d76..2d1dba6f79c8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -131,7 +131,7 @@ public class DozeSensors {
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
- mConfig.wakeScreenGestureAvailable(),
+ mConfig.wakeScreenGestureAvailable() && alwaysOn,
DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
false /* reports touch coordinates */,
false /* touchscreen */),
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index f5ac0d39d61f..7c9b2864f7f2 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -33,6 +33,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
@@ -91,6 +92,7 @@ import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.EmergencyDialerConstants;
+import com.android.systemui.util.leak.RotationUtils;
import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator;
import java.util.ArrayList;
@@ -159,6 +161,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final ScreenshotHelper mScreenshotHelper;
private final ScreenRecordHelper mScreenRecordHelper;
+ private int mLastRotation;
+
/**
* @param context everything needs a context :(
*/
@@ -201,6 +205,8 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mScreenshotHelper = new ScreenshotHelper(context);
mScreenRecordHelper = new ScreenRecordHelper(context);
+ mLastRotation = RotationUtils.getRotation(mContext);
+
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -426,6 +432,15 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
}
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ int rotation = RotationUtils.getRotation(mContext);
+ if (rotation != mLastRotation) {
+ mDialog.onRotate();
+ }
+ mLastRotation = rotation;
+ }
+
public void destroy() {
Dependency.get(ConfigurationController.class).removeCallback(this);
}
@@ -1091,7 +1106,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
protected int getActionLayoutId(Context context) {
- if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) {
+ if (isGridEnabled(context)) {
return com.android.systemui.R.layout.global_actions_grid_item;
}
return com.android.systemui.R.layout.global_actions_item;
@@ -1465,7 +1480,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private final Context mContext;
private final MyAdapter mAdapter;
- private final MultiListLayout mGlobalActionsLayout;
+ private MultiListLayout mGlobalActionsLayout;
private final OnClickListener mClickListener;
private final OnItemLongClickListener mLongClickListener;
private final GradientDrawable mGradientDrawable;
@@ -1505,8 +1520,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
window.setBackgroundDrawable(mGradientDrawable);
window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ initializeLayout();
- setContentView(getGlobalActionsLayoutId(context));
+ setTitle(R.string.global_actions);
+ }
+
+ private void initializeLayout() {
+ setContentView(getGlobalActionsLayoutId(mContext));
mGlobalActionsLayout = (MultiListLayout)
findViewById(com.android.systemui.R.id.global_actions_view);
mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
@@ -1520,11 +1540,20 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
return true;
}
});
- setTitle(R.string.global_actions);
+ }
+
+ public void onRotate() {
+ if (mShowing && isGridEnabled(mContext)) {
+ initializeLayout();
+ updateList();
+ }
}
private int getGlobalActionsLayoutId(Context context) {
- if (FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED)) {
+ if (isGridEnabled(context)) {
+ if (RotationUtils.getRotation(context) == RotationUtils.ROTATION_SEASCAPE) {
+ return com.android.systemui.R.layout.global_actions_grid_seascape;
+ }
return com.android.systemui.R.layout.global_actions_grid;
}
return com.android.systemui.R.layout.global_actions_wrapped;
@@ -1543,10 +1572,20 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
int separatedIndex = separatedActions.indexOf(action);
ViewGroup parent;
if (separatedIndex != -1) {
- parent = mGlobalActionsLayout.getParentView(true, separatedIndex);
+ parent = mGlobalActionsLayout.getParentView(true, separatedIndex, false);
} else {
+ boolean reverse = false;
+
+ // If we're using the grid layout and we're in seascape, reverse the order
+ // of sublists to make sure they render in the correct positions,
+ // since we can't reverse vertical LinearLayouts through the layout xml.
+
+ if (isGridEnabled(mContext) && RotationUtils.getRotation(mContext)
+ == RotationUtils.ROTATION_SEASCAPE) {
+ reverse = true;
+ }
int listIndex = listActions.indexOf(action);
- parent = mGlobalActionsLayout.getParentView(false, listIndex);
+ parent = mGlobalActionsLayout.getParentView(false, listIndex, reverse);
}
View v = mAdapter.getView(i, null, parent);
final int pos = i;
@@ -1665,4 +1704,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mKeyguardShowing = keyguardShowing;
}
}
+
+ /**
+ * Determines whether or not the Global Actions Dialog should use the newer grid-style layout.
+ */
+ public static boolean isGridEnabled(Context context) {
+ return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index 0e49b5f3cd2a..1d042776efc9 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -83,11 +83,11 @@ public class GlobalActionsGridLayout extends MultiListLayout {
}
@Override
- public ViewGroup getParentView(boolean separated, int index) {
+ public ViewGroup getParentView(boolean separated, int index, boolean reverseOrder) {
if (separated) {
return getSeparatedView();
} else {
- return getListView().getParentView(index);
+ return getListView().getParentView(index, reverseOrder);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
index 37755155751f..d5dcd74c7ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
@@ -28,16 +28,13 @@ import android.widget.LinearLayout;
*
* * Try to maintain a 'square' grid (equal number of columns and rows) based on the expected item
* count.
+ * * Determine the position and parent of any item by its index and the total item count.
* * Display and hide sub-lists as needed, depending on the expected item count.
- * * Favor bias toward having more rows or columns depending on the orientation of the device
- * (TODO(123344999): Implement this, currently always favors adding more rows.)
- * * Change the orientation (horizontal vs. vertical) of the container and sub-lists to act as rows
- * or columns depending on the orientation of the device.
- * (TODO(123344999): Implement this, currently always columns.)
*
* While we could implement this behavior with a GridLayout, it would take significantly more
* time and effort, and would require more substantial refactoring of the existing code in
- * GlobalActionsDialog, since it would require manipulation of the child items themselves.
+ * GlobalActionsDialog, since it would require manipulation of layout properties on the child items
+ * themselves.
*
*/
@@ -65,14 +62,25 @@ public class ListGridLayout extends LinearLayout {
/**
* Get the parent view associated with the item which should be placed at the given position.
*/
- public ViewGroup getParentView(int index) {
- ViewGroup firstParent = (ViewGroup) getChildAt(0);
+ public ViewGroup getParentView(int index, boolean reverseSublists) {
if (mRows == 0) {
- return firstParent;
+ return null;
}
+ int column = getParentViewIndex(index, reverseSublists);
+ return (ViewGroup) getChildAt(column);
+ }
+
+ private int reverseSublistIndex(int index) {
+ return getChildCount() - (index + 1);
+ }
+
+ private int getParentViewIndex(int index, boolean reverseSublists) {
int column = (int) Math.floor(index / mRows);
- ViewGroup parent = (ViewGroup) getChildAt(column);
- return parent != null ? parent : firstParent;
+ int columnCount = getChildCount();
+ if (reverseSublists) {
+ column = reverseSublistIndex(column);
+ }
+ return column;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index f7ca51d6f840..a6e48f8835c7 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -62,4 +62,6 @@ data class PrivacyApplication(val packageName: String, val uid: Int, val context
context.packageManager.getApplicationLabel(it) as String
} ?: packageName
}
+
+ override fun toString() = "PrivacyApplication(packageName=$packageName, uid=$uid)"
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 0f3393708bcd..625eacd7e2a7 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -31,6 +31,9 @@ import com.android.systemui.Dependency.MAIN_HANDLER_NAME
import com.android.systemui.R
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
+import com.android.systemui.Dumpable
+import java.io.FileDescriptor
+import java.io.PrintWriter
import java.lang.ref.WeakReference
import javax.inject.Inject
import javax.inject.Named
@@ -42,7 +45,7 @@ class PrivacyItemController @Inject constructor(
private val appOpsController: AppOpsController,
@Named(MAIN_HANDLER_NAME) private val uiHandler: Handler,
@Named(BG_HANDLER_NAME) private val bgHandler: Handler
-) {
+) : Dumpable {
companion object {
val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
@@ -56,7 +59,10 @@ class PrivacyItemController @Inject constructor(
const val SYSTEM_UID = 1000
}
- private var privacyList = emptyList<PrivacyItem>()
+ @VisibleForTesting
+ internal var privacyList = emptyList<PrivacyItem>()
+ get() = field.toList() // Provides a shallow copy of the list
+
private val userManager = context.getSystemService(UserManager::class.java)
private var currentUserIds = emptyList<Int>()
private var listening = false
@@ -189,4 +195,22 @@ class PrivacyItemController @Inject constructor(
callback?.privacyChanged(list)
}
}
+
+ override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
+ pw?.println("PrivacyItemController state:")
+ pw?.println(" Listening: $listening")
+ pw?.println(" Current user ids: $currentUserIds")
+ pw?.println(" Privacy Items:")
+ privacyList.forEach {
+ pw?.print(" ")
+ pw?.println(it.toString())
+ }
+ pw?.println(" Callbacks:")
+ callbacks.forEach {
+ it.get()?.let {
+ pw?.print(" ")
+ pw?.println(it.toString())
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 01b0bb14c7ca..110d51563e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -348,15 +348,13 @@ public class NotificationShelf extends ActivatableNotificationView implements
if (notGoneIndex == 0) {
StatusBarIconView icon = row.getEntry().expandedIcon;
NotificationIconContainer.IconState iconState = getIconState(icon);
+ // The icon state might be null in rare cases where the notification is actually
+ // added to the layout, but not to the shelf. An example are replied messages, since
+ // they don't show up on AOD
if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
// only if the first icon is fully in the shelf we want to clip to it!
backgroundTop = (int) (row.getTranslationY() - getTranslationY());
firstElementRoundness = row.getCurrentTopRoundness();
- } else if (iconState == null) {
- Log.wtf(TAG, "iconState is null. ExpandedIcon: " + row.getEntry().expandedIcon
- + (row.getEntry().expandedIcon != null
- ? "\n icon parent: " + row.getEntry().expandedIcon.getParent() : "")
- + " \n number of notifications: " + mHostLayout.getChildCount() );
}
}
if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 662cf514b977..ee5ac7c602aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -24,6 +24,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -61,7 +62,7 @@ public class NotificationViewHierarchyManager {
protected final NotificationLockscreenUserManager mLockscreenUserManager;
protected final NotificationGroupManager mGroupManager;
protected final VisualStabilityManager mVisualStabilityManager;
- private final StatusBarStateControllerImpl mStatusBarStateController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
private final NotificationEntryManager mEntryManager;
// Lazy
@@ -82,13 +83,13 @@ public class NotificationViewHierarchyManager {
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
- StatusBarStateControllerImpl statusBarStateController,
+ StatusBarStateController statusBarStateController,
NotificationEntryManager notificationEntryManager,
Lazy<ShadeController> shadeController) {
mLockscreenUserManager = notificationLockscreenUserManager;
mGroupManager = groupManager;
mVisualStabilityManager = visualStabilityManager;
- mStatusBarStateController = statusBarStateController;
+ mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
mEntryManager = notificationEntryManager;
mShadeController = shadeController;
Resources res = context.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 8f7778b4a351..69828c166463 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1213,6 +1213,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
l.initView();
l.reInflateViews();
}
+ mStatusBarNotification.clearPackageContext();
mNotificationInflater.clearCachesAndReInflate();
onNotificationUpdated();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 2799191a886f..e0c5e59b73f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -92,6 +92,8 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.NotificationChannels;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.List;
import java.util.Locale;
@@ -793,6 +795,15 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
boolean showMicrophone = false;
boolean showLocation = false;
for (PrivacyItem item : items) {
+ if (item == null /* b/124234367 */) {
+ if (DEBUG) {
+ Log.e(TAG, "updatePrivacyItems - null item found");
+ StringWriter out = new StringWriter();
+ mPrivacyItemController.dump(null, new PrintWriter(out), null);
+ Log.e(TAG, out.toString());
+ }
+ continue;
+ }
switch (item.getPrivacyType()) {
case TYPE_CAMERA:
showCamera = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index f980d074f6ef..653ec50e7682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -189,7 +189,6 @@ import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
@@ -653,7 +652,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mColorExtractor.addOnColorsChangedListener(this);
mStatusBarStateController.addCallback(this,
- StatusBarStateControllerImpl.RANK_STATUS_BAR);
+ SysuiStatusBarStateController.RANK_STATUS_BAR);
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mDreamManager = IDreamManager.Stub.asInterface(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 5d3f6cacc80f..bb384dd52875 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -35,7 +35,12 @@ import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
+import org.hamcrest.Matchers.hasItem
+import org.hamcrest.Matchers.not
+import org.hamcrest.Matchers.nullValue
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertThat
+import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -240,4 +245,26 @@ class PrivacyItemControllerTest : SysuiTestCase() {
verify(callback, never()).privacyChanged(anyList())
verify(otherCallback).privacyChanged(anyList())
}
+
+ @Test
+ fun testListShouldNotHaveNull() {
+ doReturn(listOf(AppOpItem(AppOpsManager.OP_ACTIVATE_VPN, TEST_UID, "", 0),
+ AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, "", 0)))
+ .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ privacyItemController.addCallback(callback)
+ testableLooper.processAllMessages()
+
+ verify(callback).privacyChanged(capture(argCaptor))
+ assertEquals(1, argCaptor.value.size)
+ assertThat(argCaptor.value, not(hasItem(nullValue())))
+ }
+
+ @Test
+ fun testListShouldBeCopy() {
+ val list = listOf(PrivacyItem(PrivacyType.TYPE_CAMERA,
+ PrivacyApplication("", TEST_UID, mContext)))
+ privacyItemController.privacyList = list
+ assertEquals(list, privacyItemController.privacyList)
+ assertTrue(list !== privacyItemController.privacyList)
+ }
} \ No newline at end of file
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 3c52e17ce1e8..4ed5c3d263b6 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -37,6 +37,9 @@ final class ContentCaptureServerSession {
final IBinder mActivityToken;
private final ContentCapturePerUserService mService;
private final RemoteContentCaptureService mRemoteService;
+
+ // NOTE: this is the "internal" context (like package and taskId), not the explicit content
+ // set by apps - those are only send to the ContentCaptureService.
private final ContentCaptureContext mContentCaptureContext;
/**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d1cd072ee215..dad428acbfee 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2842,6 +2842,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (DBG) {
log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
}
+ // Clear all notifications of this network.
+ mNotifier.clearNotification(nai.network.netId);
// A network agent has disconnected.
// TODO - if we move the logic to the network agent (have them disconnect
// because they lost all their requests or because their score isn't good)
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index ebd4c5584fe1..eb591528bc90 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -49,7 +49,7 @@ public abstract class ExtconUEventObserver extends UEventObserver {
private static final String TAG = "ExtconUEventObserver";
private static final boolean LOG = false;
private static final String SELINUX_POLICIES_NEED_TO_BE_CHANGED =
- "This probably mean the selinux policies need to be changed.";
+ "This probably means the selinux policies need to be changed.";
private final Map<String, ExtconInfo> mExtconInfos = new ArrayMap<>();
@@ -159,6 +159,15 @@ public abstract class ExtconUEventObserver extends UEventObserver {
/** Does the {@link /sys/class/extcon} directory exist */
public static boolean extconExists() {
File extconDir = new File("/sys/class/extcon");
- return extconDir.exists() && extconDir.isDirectory();
+ boolean retVal = extconDir.exists() && extconDir.isDirectory();
+ // TODO(b/124364409): return the correct value after selinux policy is updated.
+ if (retVal) {
+ Slog.w(TAG, extconDir + " exists " + extconDir.exists() + " isDir "
+ + extconDir.isDirectory()
+ + " but reporting it does not exist until selinux policies are updated."
+ + " see b/124364409"
+ );
+ }
+ return false;
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 3479e18b97c5..0b0934bc5a5e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -2069,7 +2069,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
if (!provider.isUseableLocked()) {
if (isSettingsExemptLocked(record)) {
- providerRequest.forceLocation = true;
+ providerRequest.locationSettingsIgnored = true;
providerRequest.lowPowerMode = false;
} else {
continue;
@@ -2079,8 +2079,9 @@ public class LocationManagerService extends ILocationManager.Stub {
LocationRequest locationRequest = record.mRealRequest;
long interval = locationRequest.getInterval();
+
// if we're forcing location, don't apply any throttling
- if (!providerRequest.forceLocation && !isThrottlingExemptLocked(
+ if (!providerRequest.locationSettingsIgnored && !isThrottlingExemptLocked(
record.mReceiver.mCallerIdentity)) {
if (!record.mIsForegroundUid) {
interval = Math.max(interval, backgroundThrottleInterval);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index f505b76178a4..dc394d0ad482 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -20,18 +20,18 @@ import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.SHUTDOWN;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_BLACKLIST;
+import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_NONE;
+import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
+import static android.net.INetd.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.INetd.FIREWALL_WHITELIST;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
-import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
-import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_ALL;
@@ -1946,7 +1946,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
int numUids = 0;
if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
- if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
+ if (getFirewallType(chain) == FIREWALL_WHITELIST) {
// Close all sockets on all non-system UIDs...
ranges = new UidRange[] {
// TODO: is there a better way of finding all existing users? If so, we could
@@ -1958,7 +1958,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
final SparseIntArray rules = getUidFirewallRulesLR(chain);
exemptUids = new int[rules.size()];
for (int i = 0; i < exemptUids.length; i++) {
- if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
+ if (rules.valueAt(i) == FIREWALL_RULE_ALLOW) {
exemptUids[numUids] = rules.keyAt(i);
numUids++;
}
@@ -1980,7 +1980,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
final SparseIntArray rules = getUidFirewallRulesLR(chain);
ranges = new UidRange[rules.size()];
for (int i = 0; i < ranges.length; i++) {
- if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
+ if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
int uid = rules.keyAt(i);
ranges[numUids] = new UidRange(uid, uid);
numUids++;
@@ -2052,13 +2052,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private int getFirewallType(int chain) {
switch (chain) {
case FIREWALL_CHAIN_STANDBY:
- return FIREWALL_TYPE_BLACKLIST;
+ return FIREWALL_BLACKLIST;
case FIREWALL_CHAIN_DOZABLE:
- return FIREWALL_TYPE_WHITELIST;
+ return FIREWALL_WHITELIST;
case FIREWALL_CHAIN_POWERSAVE:
- return FIREWALL_TYPE_WHITELIST;
+ return FIREWALL_WHITELIST;
default:
- return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
+ return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST;
}
}
@@ -2160,14 +2160,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private @NonNull String getFirewallRuleName(int chain, int rule) {
String ruleName;
- if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
- if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
+ if (getFirewallType(chain) == FIREWALL_WHITELIST) {
+ if (rule == FIREWALL_RULE_ALLOW) {
ruleName = "allow";
} else {
ruleName = "deny";
}
} else { // Blacklist mode
- if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
+ if (rule == FIREWALL_RULE_DENY) {
ruleName = "deny";
} else {
ruleName = "allow";
@@ -2194,7 +2194,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
private int getFirewallRuleType(int chain, int rule) {
if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
- return getFirewallType(chain) == FIREWALL_TYPE_WHITELIST
+ return getFirewallType(chain) == FIREWALL_WHITELIST
? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
}
return rule;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 2f1510e32311..81209763d3a8 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -246,7 +247,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private PreciseDataConnectionState mPreciseDataConnectionState =
new PreciseDataConnectionState();
- static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
+ // Nothing here yet, but putting it here in case we want to add more in the future.
+ static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = 0;
+
+ static final int ENFORCE_FINE_LOCATION_PERMISSION_MASK =
PhoneStateListener.LISTEN_CELL_LOCATION
| PhoneStateListener.LISTEN_CELL_INFO;
@@ -637,8 +641,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
try {
if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
- r.callback.onServiceStateChanged(
- new ServiceState(mServiceState[phoneId]));
+ ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(rawSs);
+ } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+ r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+ } else {
+ r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+ }
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -673,7 +683,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (DBG_LOC) log("listen: mCellLocation = "
+ mCellLocation[phoneId]);
- if (checkLocationAccess(r)) {
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellLocationChanged(
new Bundle(mCellLocation[phoneId]));
}
@@ -722,7 +732,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
+ mCellInfo.get(phoneId));
- if (checkLocationAccess(r)) {
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
}
} catch (RemoteException ex) {
@@ -1009,13 +1019,22 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) &&
idMatch(r.subId, subId, phoneId)) {
+
try {
+ ServiceState stateToSend;
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ stateToSend = new ServiceState(state);
+ } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+ stateToSend = state.sanitizeLocationInfo(false);
+ } else {
+ stateToSend = state.sanitizeLocationInfo(true);
+ }
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " state=" + state);
}
- r.callback.onServiceStateChanged(new ServiceState(state));
+ r.callback.onServiceStateChanged(stateToSend);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1198,7 +1217,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
idMatch(r.subId, subId, phoneId) &&
- checkLocationAccess(r)) {
+ checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
try {
if (DBG_LOC) {
log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
@@ -1500,7 +1519,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
- checkLocationAccess(r)) {
+ checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
try {
if (DBG_LOC) {
log("notifyCellLocation: cellLocation=" + cellLocation
@@ -2108,12 +2127,35 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private boolean checkListenerPermission(
int events, int subId, String callingPackage, String message) {
+ LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
+ new LocationAccessPolicy.LocationPermissionQuery.Builder()
+ .setCallingPackage(callingPackage)
+ .setMethod(message + " events: " + events)
+ .setCallingPid(Binder.getCallingPid())
+ .setCallingUid(Binder.getCallingUid());
+
+ boolean shouldCheckLocationPermissions = false;
if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
- if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
- callingPackage) != AppOpsManager.MODE_ALLOWED) {
- return false;
+ locationQueryBuilder.setMinSdkVersionForCoarse(0);
+ shouldCheckLocationPermissions = true;
+ }
+
+ if ((events & ENFORCE_FINE_LOCATION_PERMISSION_MASK) != 0) {
+ // Everything that requires fine location started in Q. So far...
+ locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q);
+ shouldCheckLocationPermissions = true;
+ }
+
+ if (shouldCheckLocationPermissions) {
+ LocationAccessPolicy.LocationPermissionResult result =
+ LocationAccessPolicy.checkLocationPermission(
+ mContext, locationQueryBuilder.build());
+ switch (result) {
+ case DENIED_HARD:
+ throw new SecurityException("Unable to listen for events " + events + " due to "
+ + "insufficient location permissions.");
+ case DENIED_SOFT:
+ return false;
}
}
@@ -2228,15 +2270,38 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- private boolean checkLocationAccess(Record r) {
- long token = Binder.clearCallingIdentity();
- try {
- return LocationAccessPolicy.canAccessCellLocation(mContext,
- r.callingPackage, r.callerUid, r.callerPid,
- /*throwOnDeniedPermission*/ false);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ private boolean checkFineLocationAccess(Record r, int minSdk) {
+ LocationAccessPolicy.LocationPermissionQuery query =
+ new LocationAccessPolicy.LocationPermissionQuery.Builder()
+ .setCallingPackage(r.callingPackage)
+ .setCallingPid(r.callerPid)
+ .setCallingUid(r.callerUid)
+ .setMethod("TelephonyRegistry push")
+ .setMinSdkVersionForFine(minSdk)
+ .build();
+
+ return Binder.withCleanCallingIdentity(() -> {
+ LocationAccessPolicy.LocationPermissionResult locationResult =
+ LocationAccessPolicy.checkLocationPermission(mContext, query);
+ return locationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
+ });
+ }
+
+ private boolean checkCoarseLocationAccess(Record r, int minSdk) {
+ LocationAccessPolicy.LocationPermissionQuery query =
+ new LocationAccessPolicy.LocationPermissionQuery.Builder()
+ .setCallingPackage(r.callingPackage)
+ .setCallingPid(r.callerPid)
+ .setCallingUid(r.callerUid)
+ .setMethod("TelephonyRegistry push")
+ .setMinSdkVersionForCoarse(minSdk)
+ .build();
+
+ return Binder.withCleanCallingIdentity(() -> {
+ LocationAccessPolicy.LocationPermissionResult locationResult =
+ LocationAccessPolicy.checkLocationPermission(mContext, query);
+ return locationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
+ });
}
private void checkPossibleMissNotify(Record r, int phoneId) {
@@ -2286,7 +2351,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
+ mCellInfo.get(phoneId));
}
- if (checkLocationAccess(r)) {
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
}
} catch (RemoteException ex) {
@@ -2336,7 +2401,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
try {
if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
+ mCellLocation[phoneId]);
- if (checkLocationAccess(r)) {
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
}
} catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c4a9db6b7262..2f20572caa99 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18100,8 +18100,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (!queue.isIdle()) {
final String msg = "Waiting for queue " + queue + " to become idle...";
pw.println(msg);
+ pw.println(queue.describeState());
pw.flush();
Slog.v(TAG, msg);
+ queue.cancelDeferrals();
idle = false;
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java
index 6371cd376d19..0b38ef94de1e 100644
--- a/services/core/java/com/android/server/am/BroadcastDispatcher.java
+++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java
@@ -65,6 +65,14 @@ public class BroadcastDispatcher {
broadcasts.add(br);
}
+ int size() {
+ return broadcasts.size();
+ }
+
+ boolean isEmpty() {
+ return broadcasts.isEmpty();
+ }
+
void writeToProto(ProtoOutputStream proto, long fieldId) {
for (BroadcastRecord br : broadcasts) {
br.writeToProto(proto, fieldId);
@@ -252,22 +260,48 @@ public class BroadcastDispatcher {
synchronized (mLock) {
return mCurrentBroadcast == null
&& mOrderedBroadcasts.isEmpty()
- && mDeferredBroadcasts.isEmpty()
- && mAlarmBroadcasts.isEmpty();
+ && isDeferralsListEmpty(mDeferredBroadcasts)
+ && isDeferralsListEmpty(mAlarmBroadcasts);
+ }
+ }
+
+ private static int pendingInDeferralsList(ArrayList<Deferrals> list) {
+ int pending = 0;
+ final int numEntries = list.size();
+ for (int i = 0; i < numEntries; i++) {
+ pending += list.get(i).size();
}
+ return pending;
+ }
+
+ private static boolean isDeferralsListEmpty(ArrayList<Deferrals> list) {
+ return pendingInDeferralsList(list) == 0;
}
/**
- * Not quite the traditional size() measurement; includes any in-process but
- * not yet retired active outbound broadcast.
+ * Strictly for logging, describe the currently pending contents in a human-
+ * readable way
*/
- public int totalUndelivered() {
- synchronized (mLock) {
- return mAlarmBroadcasts.size()
- + mDeferredBroadcasts.size()
- + mOrderedBroadcasts.size()
- + (mCurrentBroadcast == null ? 0 : 1);
- }
+ public String describeStateLocked() {
+ final StringBuilder sb = new StringBuilder(128);
+ if (mCurrentBroadcast != null) {
+ sb.append("1 in flight, ");
+ }
+ sb.append(mOrderedBroadcasts.size());
+ sb.append(" ordered");
+ int n = pendingInDeferralsList(mAlarmBroadcasts);
+ if (n > 0) {
+ sb.append(", ");
+ sb.append(n);
+ sb.append(" deferrals in alarm recipients");
+ }
+ n = pendingInDeferralsList(mDeferredBroadcasts);
+ if (n > 0) {
+ sb.append(", ");
+ sb.append(n);
+ sb.append(" deferred");
+ }
+ return sb.toString();
}
// ----------------------------------
@@ -579,6 +613,26 @@ public class BroadcastDispatcher {
}
}
+ /**
+ * Cancel all current deferrals; that is, make all currently-deferred broadcasts
+ * immediately deliverable. Used by the wait-for-broadcast-idle mechanism.
+ */
+ public void cancelDeferrals() {
+ synchronized (mLock) {
+ zeroDeferralTimes(mAlarmBroadcasts);
+ zeroDeferralTimes(mDeferredBroadcasts);
+ }
+ }
+
+ private static void zeroDeferralTimes(ArrayList<Deferrals> list) {
+ final int num = list.size();
+ for (int i = 0; i < num; i++) {
+ Deferrals d = list.get(i);
+ // Safe to do this in-place because it won't break ordering
+ d.deferUntil = d.deferredBy = 0;
+ }
+ }
+
// ----------------------------------
/**
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index ad7158d25637..d9ea1da79f56 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -928,8 +928,8 @@ public final class BroadcastQueue {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
+ mQueueName + "]: "
- + mParallelBroadcasts.size() + " parallel broadcasts, "
- + mDispatcher.totalUndelivered() + " ordered broadcasts");
+ + mParallelBroadcasts.size() + " parallel broadcasts; "
+ + mDispatcher.describeStateLocked());
mService.updateCpuStats();
@@ -1827,11 +1827,24 @@ public final class BroadcastQueue {
record.intent == null ? "" : record.intent.getAction());
}
- final boolean isIdle() {
+ boolean isIdle() {
return mParallelBroadcasts.isEmpty() && mDispatcher.isEmpty()
&& (mPendingBroadcast == null);
}
+ // Used by wait-for-broadcast-idle : fast-forward all current deferrals to
+ // be immediately deliverable.
+ void cancelDeferrals() {
+ mDispatcher.cancelDeferrals();
+ }
+
+ String describeState() {
+ synchronized (mService) {
+ return mParallelBroadcasts.size() + " parallel; "
+ + mDispatcher.describeStateLocked();
+ }
+ }
+
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName);
diff --git a/services/core/java/com/android/server/appbinding/AppBindingService.java b/services/core/java/com/android/server/appbinding/AppBindingService.java
index 0b6a4329d15b..bbe4ed15b3a0 100644
--- a/services/core/java/com/android/server/appbinding/AppBindingService.java
+++ b/services/core/java/com/android/server/appbinding/AppBindingService.java
@@ -177,13 +177,12 @@ public class AppBindingService extends Binder {
* Handle boot phase PHASE_ACTIVITY_MANAGER_READY.
*/
private void onPhaseActivityManagerReady() {
+ // RoleManager doesn't tell us about upgrade, so we still need to listen for app upgrades.
+ // (app uninstall/disable will be notified by RoleManager.)
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addDataScheme("package");
- packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mPackageUserMonitor, UserHandle.ALL,
packageFilter, null, mHandler);
@@ -256,14 +255,6 @@ public class AppBindingService extends Binder {
handlePackageAddedReplacing(packageName, userId);
}
break;
- case Intent.ACTION_PACKAGE_REMOVED:
- if (!replacing) {
- handlePackageRemoved(packageName, userId);
- }
- break;
- case Intent.ACTION_PACKAGE_CHANGED:
- handlePackageChanged(packageName, userId);
- break;
}
}
};
@@ -371,31 +362,6 @@ public class AppBindingService extends Binder {
}
}
- private void handlePackageRemoved(String packageName, int userId) {
- if (DEBUG) {
- Slog.d(TAG, "handlePackageRemoved: u" + userId + " " + packageName);
- }
- synchronized (mLock) {
- final AppServiceFinder finder = findFinderLocked(userId, packageName);
- if (finder != null) {
- unbindServicesLocked(userId, finder, "package uninstall");
- }
- }
- }
-
- private void handlePackageChanged(String packageName, int userId) {
- if (DEBUG) {
- Slog.d(TAG, "handlePackageChanged: u" + userId + " " + packageName);
- }
- synchronized (mLock) {
- final AppServiceFinder finder = findFinderLocked(userId, packageName);
- if (finder != null) {
- unbindServicesLocked(userId, finder, "package changed");
- bindServicesLocked(userId, finder, "package changed");
- }
- }
- }
-
private void rebindAllLocked(String reason) {
for (int i = 0; i < mRunningUsers.size(); i++) {
if (!mRunningUsers.valueAt(i)) {
diff --git a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
index 4c5f1a1c7b49..753d3b0cc10e 100644
--- a/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
+++ b/services/core/java/com/android/server/appbinding/finders/CarrierMessagingClientServiceFinder.java
@@ -16,14 +16,10 @@
package com.android.server.appbinding.finders;
-import static android.provider.Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL;
-
import android.Manifest.permission;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IBinder;
@@ -35,7 +31,8 @@ import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.R;
-import com.android.internal.telephony.SmsApplication;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.CollectionUtils;
import com.android.server.appbinding.AppBindingConstants;
import java.util.function.BiConsumer;
@@ -45,10 +42,15 @@ import java.util.function.BiConsumer;
*/
public class CarrierMessagingClientServiceFinder
extends AppServiceFinder<CarrierMessagingClientService, ICarrierMessagingClientService> {
+
+ private final RoleManager mRoleManager;
+
public CarrierMessagingClientServiceFinder(Context context,
BiConsumer<AppServiceFinder, Integer> listener,
Handler callbackHandler) {
super(context, listener, callbackHandler);
+
+ mRoleManager = context.getSystemService(RoleManager.class);
}
@Override
@@ -84,9 +86,8 @@ public class CarrierMessagingClientServiceFinder
@Override
public String getTargetPackage(int userId) {
- final ComponentName cn = SmsApplication.getDefaultSmsApplicationAsUser(
- mContext, /* updateIfNeeded= */ true, userId);
- String ret = cn == null ? null : cn.getPackageName();
+ final String ret = CollectionUtils.firstOrNull(mRoleManager.getRoleHoldersAsUser(
+ RoleManager.ROLE_SMS, UserHandle.of(userId)));
if (DEBUG) {
Slog.d(TAG, "getTargetPackage()=" + ret);
@@ -97,9 +98,8 @@ public class CarrierMessagingClientServiceFinder
@Override
public void startMonitoring() {
- final IntentFilter filter = new IntentFilter(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
- mContext.registerReceiverAsUser(mSmsAppChangedWatcher, UserHandle.ALL, filter,
- /* permission= */ null, mHandler);
+ mRoleManager.addOnRoleHoldersChangedListenerAsUser(
+ mContext.getMainExecutor(), mRoleHolderChangedListener, UserHandle.ALL);
}
@Override
@@ -118,12 +118,11 @@ public class CarrierMessagingClientServiceFinder
return constants.SMS_APP_BIND_FLAGS;
}
- private final BroadcastReceiver mSmsAppChangedWatcher = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL.equals(intent.getAction())) {
- mListener.accept(CarrierMessagingClientServiceFinder.this, getSendingUserId());
- }
+ private final OnRoleHoldersChangedListener mRoleHolderChangedListener = (role, user) -> {
+ if (RoleManager.ROLE_SMS.equals(role)) {
+ BackgroundThread.getHandler().post(() -> {
+ mListener.accept(CarrierMessagingClientServiceFinder.this, user.getIdentifier());
+ });
}
};
}
diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java
index a68ceed750ad..6899c3ffcbb1 100644
--- a/services/core/java/com/android/server/gpu/GpuService.java
+++ b/services/core/java/com/android/server/gpu/GpuService.java
@@ -22,24 +22,33 @@ import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.gamedriver.GameDriverProto.Blacklist;
+import android.gamedriver.GameDriverProto.Blacklists;
import android.net.Uri;
import android.os.Build;
+import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.Base64;
import android.util.Slog;
+import com.android.framework.protobuf.InvalidProtocolBufferException;
+import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.List;
/**
* Service to manage GPU related features.
@@ -52,17 +61,25 @@ public class GpuService extends SystemService {
public static final boolean DEBUG = false;
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
- private static final String WHITELIST_FILENAME = "whitelist.txt";
+ private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt";
+ private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP;
private final Context mContext;
private final String mDriverPackageName;
private final PackageManager mPackageManager;
+ private final Object mLock = new Object();
+ private ContentResolver mContentResolver;
+ private long mGameDriverVersionCode;
+ private SettingsObserver mSettingsObserver;
+ @GuardedBy("mLock")
+ private Blacklists mBlacklists;
public GpuService(Context context) {
super(context);
mContext = context;
mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
+ mGameDriverVersionCode = -1;
mPackageManager = context.getPackageManager();
if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) {
final IntentFilter packageFilter = new IntentFilter();
@@ -82,10 +99,37 @@ public class GpuService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_BOOT_COMPLETED) {
+ mContentResolver = mContext.getContentResolver();
+ mSettingsObserver = new SettingsObserver();
if (mDriverPackageName == null || mDriverPackageName.isEmpty()) {
return;
}
fetchGameDriverPackageProperties();
+ processBlacklists();
+ setBlacklist();
+ }
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private final Uri mGameDriverBlackUri =
+ Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_BLACKLISTS);
+
+ SettingsObserver() {
+ super(new Handler());
+ mContentResolver.registerContentObserver(mGameDriverBlackUri, false, this,
+ UserHandle.USER_ALL);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (uri == null) {
+ return;
+ }
+
+ if (mGameDriverBlackUri.equals(uri)) {
+ processBlacklists();
+ setBlacklist();
+ }
}
}
@@ -109,6 +153,7 @@ public class GpuService extends SystemService {
case ACTION_PACKAGE_CHANGED:
case ACTION_PACKAGE_REMOVED:
fetchGameDriverPackageProperties();
+ setBlacklist();
break;
default:
// do nothing
@@ -138,16 +183,22 @@ public class GpuService extends SystemService {
return;
}
+ // Reset the whitelist.
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.GAME_DRIVER_WHITELIST, "");
+ mGameDriverVersionCode = driverInfo.longVersionCode;
+
try {
final Context driverContext = mContext.createPackageContext(mDriverPackageName,
Context.CONTEXT_RESTRICTED);
final BufferedReader reader = new BufferedReader(
- new InputStreamReader(driverContext.getAssets().open(WHITELIST_FILENAME)));
+ new InputStreamReader(driverContext.getAssets()
+ .open(GAME_DRIVER_WHITELIST_FILENAME)));
final ArrayList<String> whitelistedPackageNames = new ArrayList<>();
for (String packageName; (packageName = reader.readLine()) != null; ) {
whitelistedPackageNames.add(packageName);
}
- Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.putString(mContentResolver,
Settings.Global.GAME_DRIVER_WHITELIST,
String.join(",", whitelistedPackageNames));
} catch (PackageManager.NameNotFoundException e) {
@@ -160,4 +211,48 @@ public class GpuService extends SystemService {
}
}
}
+
+ private void processBlacklists() {
+ // TODO(b/121350991) Switch to DeviceConfig with property listener.
+ String base64String =
+ Settings.Global.getString(mContentResolver, Settings.Global.GAME_DRIVER_BLACKLISTS);
+ if (base64String == null || base64String.isEmpty()) {
+ return;
+ }
+
+ synchronized (mLock) {
+ // Reset all blacklists
+ mBlacklists = null;
+ try {
+ mBlacklists = Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS));
+ } catch (IllegalArgumentException e) {
+ if (DEBUG) {
+ Slog.w(TAG, "Can't parse blacklist, skip and continue...");
+ }
+ } catch (InvalidProtocolBufferException e) {
+ if (DEBUG) {
+ Slog.w(TAG, "Can't parse blacklist, skip and continue...");
+ }
+ }
+ }
+ }
+
+ private void setBlacklist() {
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.GAME_DRIVER_BLACKLIST, "");
+ synchronized (mLock) {
+ if (mBlacklists == null) {
+ return;
+ }
+ List<Blacklist> blacklists = mBlacklists.getBlacklistsList();
+ for (Blacklist blacklist : blacklists) {
+ if (blacklist.getVersionCode() == mGameDriverVersionCode) {
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.GAME_DRIVER_BLACKLIST,
+ String.join(",", blacklist.getPackageNamesList()));
+ return;
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 3abacc2c9c10..e71b156c3e86 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -917,7 +917,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
synchronized (mLock) {
boolean enabled =
((mProviderRequest != null && mProviderRequest.reportLocation
- && mProviderRequest.forceLocation) || (
+ && mProviderRequest.locationSettingsIgnored) || (
mContext.getSystemService(LocationManager.class).isLocationEnabled()
&& !mDisableGps)) && !mShutdown;
if (enabled == mEnabled) {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b6ef180f4b59..b221241c25e2 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -1207,6 +1207,15 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
}
+ public void setPlaybackSpeed(String packageName, int pid, int uid,
+ ControllerCallbackLink caller, float speed) {
+ try {
+ mCb.notifySetPlaybackSpeed(packageName, pid, uid, caller, speed);
+ } catch (RuntimeException e) {
+ Slog.e(TAG, "Remote failure in setPlaybackSpeed.", e);
+ }
+ }
+
public void adjustVolume(String packageName, int pid, int uid,
ControllerCallbackLink caller, boolean asSystemService, int direction) {
try {
@@ -1446,6 +1455,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
+ public void setPlaybackSpeed(String packageName, ControllerCallbackLink caller,
+ float speed) {
+ mSessionCb.setPlaybackSpeed(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
+ caller, speed);
+ }
+
+ @Override
public void sendCustomAction(String packageName, ControllerCallbackLink caller,
String action, Bundle args) {
mSessionCb.sendCustomAction(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 9e5b92a6b944..3f15b381c18b 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -17,9 +17,6 @@
package com.android.server.net;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.provider.Settings.ACTION_VPN_SETTINGS;
import android.app.Notification;
@@ -30,17 +27,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
-import android.net.LinkProperties;
import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
-import android.net.NetworkPolicyManager;
import android.os.INetworkManagementService;
-import android.os.RemoteException;
import android.security.Credentials;
import android.security.KeyStore;
-import android.system.Os;
import android.text.TextUtils;
import android.util.Slog;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 4bd8f450c76b..6d82c1c257ab 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,15 +15,15 @@
*/
package com.android.server.net;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
+import static android.net.INetd.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import android.app.ActivityManager;
import android.net.NetworkPolicyManager;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index af55605975ca..75b62cb349af 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -38,6 +38,11 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLE
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
+import static android.net.INetd.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -45,12 +50,7 @@ import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 400443a16fab..48a4862c3f08 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3306,7 +3306,8 @@ public class PackageManagerService extends IPackageManager.Stub
// feature flags should cause us to invalidate any caches.
final String cacheName = SystemProperties.digestOf(
"ro.build.fingerprint",
- "persist.sys.isolated_storage");
+ StorageManager.PROP_ISOLATED_STORAGE,
+ StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT);
// Reconcile cache directories, keeping only what we'd actually use.
for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) {
@@ -12803,7 +12804,7 @@ public class PackageManagerService extends IPackageManager.Stub
public String[] setDistractingPackageRestrictionsAsUser(String[] packageNames,
int restrictionFlags, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
- "setPackagesSuspendedAsUser");
+ "setDistractingPackageRestrictionsAsUser");
final int callingUid = Binder.getCallingUid();
if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
@@ -19568,8 +19569,17 @@ public class PackageManagerService extends IPackageManager.Stub
parser.setInput(new ByteArrayInputStream(backup), StandardCharsets.UTF_8.name());
restoreFromXml(parser, userId, TAG_DEFAULT_APPS,
(parser1, userId1) -> {
+ String defaultBrowser;
synchronized (mPackages) {
mSettings.readDefaultAppsLPw(parser1, userId1);
+ defaultBrowser = mSettings.removeDefaultBrowserPackageNameLPw(userId1);
+ }
+ if (defaultBrowser != null) {
+ PackageManagerInternal.DefaultBrowserProvider provider;
+ synchronized (mPackages) {
+ provider = mDefaultBrowserProvider;
+ }
+ provider.setDefaultBrowser(defaultBrowser, userId1);
}
});
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 30c2281b07f1..6c212d63d77c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -156,12 +156,8 @@ public class StagingManager {
boolean success = true;
// STOPSHIP: TODO(b/123753157): Verify APKs through Package Verifier.
- if (!sessionContainsApex(session)) {
- // TODO: Decide whether we want to fail fast by detecting signature mismatches for APKs,
- // right away.
- session.setStagedSessionReady();
- return;
- }
+ // TODO: Decide whether we want to fail fast by detecting signature mismatches for APKs,
+ // right away.
final ApexInfoList apexInfoList = new ApexInfoList();
// APEX checks. For single-package sessions, check if they contain an APEX. For
@@ -227,7 +223,8 @@ public class StagingManager {
}
session.setStagedSessionReady();
- if (!mApexManager.markStagedSessionReady(session.sessionId)) {
+ if (sessionContainsApex(session)
+ && !mApexManager.markStagedSessionReady(session.sessionId)) {
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"APEX staging failed, check logcat messages from apexd for more "
+ "details.");
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 2036ed73fdf2..bd577598a617 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -721,7 +721,7 @@ public final class DefaultPermissionGrantPolicy {
grantSystemFixedPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackage(
RingtoneManager.ACTION_RINGTONE_PICKER, userId),
- userId, STORAGE_PERMISSIONS);
+ userId, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
// TextClassifier Service
String textClassifierPackageName =
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 4186154016e2..8740256af04d 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -123,6 +123,9 @@ public class AttentionDetector {
public AttentionDetector(Runnable onUserAttention, Object lock) {
mOnUserAttention = onUserAttention;
mLock = lock;
+
+ // Device starts with an awake state upon boot.
+ mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
}
public void systemReady(Context context) {
@@ -145,7 +148,7 @@ public class AttentionDetector {
if (DEBUG) {
Slog.d(TAG, "Do not check for attention yet, wait " + (whenToCheck - now));
}
- return nextScreenDimming;
+ return whenToCheck;
} else if (whenToStopExtending < whenToCheck) {
if (DEBUG) {
Slog.d(TAG, "Let device sleep to avoid false results and improve security "
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 95c3f4c43313..ceaf829290d7 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -40,6 +40,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.provider.DeviceConfig;
import android.util.IntArray;
import android.util.Log;
import android.util.SparseBooleanArray;
@@ -61,6 +62,7 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/**
* Implementation of service that manages APK level rollbacks.
@@ -71,13 +73,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// Rollbacks expire after 48 hours.
// TODO: How to test rollback expiration works properly?
- private static final long ROLLBACK_LIFETIME_DURATION_MILLIS = 48 * 60 * 60 * 1000;
+ private static final long DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS =
+ TimeUnit.HOURS.toMillis(48);
// Lock used to synchronize accesses to in-memory rollback data
// structures. By convention, methods with the suffix "Locked" require
// mLock is held when they are called.
private final Object mLock = new Object();
+ // No need for guarding with lock because value is only accessed in handler thread
+ // and the value will be written on boot complete. Initialization here happens before
+ // handler threads are running so that's fine.
+ private long mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
+
// Used for generating rollback IDs.
private final Random mRandom = new SecureRandom();
@@ -484,7 +492,25 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
});
}
+ private void updateRollbackLifetimeDurationInMillis() {
+ String strRollbackLifetimeInMillis = DeviceConfig.getProperty(
+ DeviceConfig.Rollback.BOOT_NAMESPACE,
+ DeviceConfig.Rollback.ROLLBACK_LIFETIME_IN_MILLIS);
+
+ try {
+ mRollbackLifetimeDurationInMillis = (strRollbackLifetimeInMillis == null)
+ ? DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS
+ : Long.parseLong(strRollbackLifetimeInMillis);
+ } catch (NumberFormatException e) {
+ mRollbackLifetimeDurationInMillis = DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS;
+ }
+ }
+
void onBootCompleted() {
+ getHandler().post(() -> updateRollbackLifetimeDurationInMillis());
+ // Also posts to handler thread
+ scheduleExpiration(0);
+
getHandler().post(() -> {
// Check to see if any staged sessions with rollback enabled have
// been applied.
@@ -565,8 +591,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (RollbackInfo info : mRecentlyExecutedRollbacks) {
mAllocatedRollbackIds.put(info.getRollbackId(), true);
}
-
- scheduleExpiration(0);
}
/**
@@ -700,8 +724,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
if (!data.isAvailable) {
continue;
}
-
- if (!now.isBefore(data.timestamp.plusMillis(ROLLBACK_LIFETIME_DURATION_MILLIS))) {
+ if (!now.isBefore(data.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
iter.remove();
deleteRollback(data);
} else if (oldest == null || oldest.isAfter(data.timestamp)) {
@@ -711,7 +734,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
if (oldest != null) {
- scheduleExpiration(now.until(oldest.plusMillis(ROLLBACK_LIFETIME_DURATION_MILLIS),
+ scheduleExpiration(now.until(oldest.plusMillis(mRollbackLifetimeDurationInMillis),
ChronoUnit.MILLIS));
}
}
@@ -1144,8 +1167,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
packages.add(data.packages.get(i).getPackageName());
}
mPackageHealthObserver.startObservingHealth(packages,
- ROLLBACK_LIFETIME_DURATION_MILLIS);
- scheduleExpiration(ROLLBACK_LIFETIME_DURATION_MILLIS);
+ mRollbackLifetimeDurationInMillis);
+ scheduleExpiration(mRollbackLifetimeDurationInMillis);
} catch (IOException e) {
Log.e(TAG, "Unable to enable rollback", e);
deleteRollback(data);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0251efb872bc..f33c518941e5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2677,8 +2677,9 @@ final class ActivityRecord extends ConfigurationContainer {
* Get the configuration orientation by the requested screen orientation
* ({@link ActivityInfo.ScreenOrientation}) of this activity.
*
- * @return orientation in ({@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT},
- * {@link #ORIENTATION_UNDEFINED}).
+ * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+ * {@link Configuration#ORIENTATION_PORTRAIT},
+ * {@link Configuration#ORIENTATION_UNDEFINED}).
*/
int getRequestedConfigurationOrientation() {
final int screenOrientation = getOrientation();
@@ -2936,14 +2937,36 @@ final class ActivityRecord extends ConfigurationContainer {
// should be given the aspect ratio.
activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
}
- } else if (containingRatio < minAspectRatio && minAspectRatio != 0) {
- if (containingAppWidth < containingAppHeight) {
- // Width is the shorter side, so we use the height to figure-out what the max. width
- // should be given the aspect ratio.
+ } else if (containingRatio < minAspectRatio) {
+ boolean adjustWidth;
+ switch (getRequestedConfigurationOrientation()) {
+ case ORIENTATION_LANDSCAPE:
+ // Width should be the longer side for this landscape app, so we use the width
+ // to figure-out what the max. height should be given the aspect ratio.
+ adjustWidth = false;
+ break;
+ case ORIENTATION_PORTRAIT:
+ // Height should be the longer side for this portrait app, so we use the height
+ // to figure-out what the max. width should be given the aspect ratio.
+ adjustWidth = true;
+ break;
+ default:
+ // This app doesn't have a preferred orientation, so we keep the length of the
+ // longer side, and use it to figure-out the length of the shorter side.
+ if (containingAppWidth < containingAppHeight) {
+ // Width is the shorter side, so we use the height to figure-out what the
+ // max. width should be given the aspect ratio.
+ adjustWidth = true;
+ } else {
+ // Height is the shorter side, so we use the width to figure-out what the
+ // max. height should be given the aspect ratio.
+ adjustWidth = false;
+ }
+ break;
+ }
+ if (adjustWidth) {
activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
} else {
- // Height is the shorter side, so we use the width to figure-out what the max.
- // height should be given the aspect ratio.
activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5cfc20b6339f..4795555e8ed2 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1500,8 +1500,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
- mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
mDisplayPolicy.configure(width, height, shortSizeDp);
+ mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2ee30ac5c8ff..91d573defc16 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2617,9 +2617,8 @@ public class DisplayPolicy {
DisplayCutout displayCutout) {
int width = fullWidth;
if (hasNavigationBar()) {
- // For a basic navigation bar, when we are in landscape mode we place
- // the navigation bar to the side.
- if (navigationBarCanMove() && fullWidth > fullHeight) {
+ final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
+ if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
width -= getNavigationBarWidth(rotation, uiMode);
}
}
@@ -2646,9 +2645,8 @@ public class DisplayPolicy {
DisplayCutout displayCutout) {
int height = fullHeight;
if (hasNavigationBar()) {
- // For a basic navigation bar, when we are in portrait mode we place
- // the navigation bar to the bottom.
- if (!navigationBarCanMove() || fullWidth < fullHeight) {
+ final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
+ if (navBarPosition == NAV_BAR_BOTTOM) {
height -= getNavigationBarHeight(rotation, uiMode);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 5f341ee8002c..543f19655350 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -38,6 +38,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.DisplayCutout;
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
@@ -70,6 +71,8 @@ public class DisplayRotation {
private final int mDeskDockRotation;
private final int mUndockedHdmiRotation;
+ private final float mCloseToSquareMaxAspectRatio;
+
private OrientationListener mOrientationListener;
private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver;
@@ -132,6 +135,9 @@ public class DisplayRotation {
mUndockedHdmiRotation = readRotation(
com.android.internal.R.integer.config_undockedHdmiRotation);
+ mCloseToSquareMaxAspectRatio = mContext.getResources().getFloat(
+ com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
+
if (isDefaultDisplay) {
final Handler uiHandler = UiThread.getHandler();
mOrientationListener = new OrientationListener(mContext, uiHandler);
@@ -212,10 +218,12 @@ public class DisplayRotation {
// so if the orientation is forced, we need to respect that no matter what.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
+ final boolean isCloseToSquare =
+ isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
final boolean forceDefaultOrientationInRes =
res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
final boolean forceDefaultOrienation =
- ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv)
+ ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv || isCloseToSquare)
&& forceDefaultOrientationInRes
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
@@ -227,6 +235,18 @@ public class DisplayRotation {
setFixedToUserRotation(forceDefaultOrienation);
}
+ private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
+ final DisplayCutout displayCutout =
+ mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
+ final int uiMode = mService.mPolicy.getUiMode();
+ final int w = mDisplayPolicy.getNonDecorDisplayWidth(
+ width, height, rotation, uiMode, displayCutout);
+ final int h = mDisplayPolicy.getNonDecorDisplayHeight(
+ width, height, rotation, uiMode, displayCutout);
+ final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h);
+ return aspectRatio <= mCloseToSquareMaxAspectRatio;
+ }
+
void setRotation(int rotation) {
if (mOrientationListener != null) {
mOrientationListener.setCurrentRotation(rotation);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index c747c6d95fcd..168c9adb61be 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -446,7 +446,8 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean mLimitedAlphaCompositing;
final int mMaxUiWidth;
- final WindowManagerPolicy mPolicy;
+ @VisibleForTesting
+ WindowManagerPolicy mPolicy;
final IActivityManager mActivityManager;
// TODO: Probably not needed once activities are fully in WM.
@@ -4263,9 +4264,12 @@ public class WindowManagerService extends IWindowManager.Stub
if (mMaxUiWidth > 0) {
mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
}
- applyForcedPropertiesForDefaultDisplay();
+ final boolean changed = applyForcedPropertiesForDefaultDisplay();
mAnimator.ready();
mDisplayReady = true;
+ if (changed) {
+ reconfigureDisplayLocked(getDefaultDisplayContentLocked());
+ }
mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TOUCHSCREEN);
}
@@ -4865,7 +4869,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
/** The global settings only apply to default display. */
- private void applyForcedPropertiesForDefaultDisplay() {
+ private boolean applyForcedPropertiesForDefaultDisplay() {
+ boolean changed = false;
final DisplayContent displayContent = getDefaultDisplayContentLocked();
// Display size.
String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
@@ -4885,6 +4890,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
displayContent.updateBaseDisplayMetrics(width, height,
displayContent.mBaseDisplayDensity);
+ changed = true;
}
} catch (NumberFormatException ex) {
}
@@ -4893,17 +4899,20 @@ public class WindowManagerService extends IWindowManager.Stub
// Display density.
final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
- if (density != 0) {
+ if (density != 0 && density != displayContent.mBaseDisplayDensity) {
displayContent.mBaseDisplayDensity = density;
+ changed = true;
}
// Display scaling mode.
int mode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DISPLAY_SCALING_FORCE, 0);
- if (mode != 0) {
+ if (displayContent.mDisplayScalingDisabled != (mode != 0)) {
Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
displayContent.mDisplayScalingDisabled = true;
+ changed = true;
}
+ return changed;
}
@Override
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 638ec95ec544..9946cc3db0e8 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,6 +1,9 @@
java_library_static {
name: "services.net",
srcs: ["java/**/*.java"],
+ static_libs: [
+ "netd_aidl_interface-java",
+ ]
}
filegroup {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
index 4bac200a22c6..ebbebcb02923 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
@@ -16,12 +16,12 @@
package com.android.server;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
+import static android.net.INetd.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import static android.util.DebugUtils.valueToString;
import static org.junit.Assert.assertEquals;
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 9f1cbcd7ec27..6a937fabd3ec 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -98,6 +98,15 @@ public class AttentionDetectorTest extends AndroidTestCase {
}
@Test
+ public void testUpdateUserActivity_schedulesTheNextCheck() {
+ long now = SystemClock.uptimeMillis();
+ mNextDimming = now;
+ mAttentionDetector.onUserActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
+ long nextTimeout = mAttentionDetector.updateUserActivity(mNextDimming + 5000L);
+ assertThat(nextTimeout).isEqualTo(mNextDimming + 5000L);
+ }
+
+ @Test
public void testOnUserActivity_ignoresAfterMaximumExtension() {
long now = SystemClock.uptimeMillis();
mAttentionDetector.onUserActivity(now - 15000L, PowerManager.USER_ACTIVITY_EVENT_TOUCH);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index a7520dcbcff9..2627ec762d7a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -30,6 +30,7 @@ import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -48,6 +49,7 @@ import org.junit.Test;
* atest WmTests:AppChangeTransitionTests
*/
@SmallTest
+@Presubmit
public class AppChangeTransitionTests extends WindowTestsBase {
private TaskStack mStack;
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 cd1320986972..1dd72ec4fd71 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -51,7 +51,6 @@ import android.platform.test.annotations.Presubmit;
import android.view.Surface;
import android.view.WindowManager;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Before;
@@ -142,7 +141,6 @@ public class AppWindowTokenTests extends WindowTestsBase {
mToken.removeImmediately();
}
- @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
@Test
public void testLandscapeSeascapeRotationByApp() {
// Some plumbing to get the service ready for rotation updates.
@@ -303,7 +301,6 @@ public class AppWindowTokenTests extends WindowTestsBase {
}
@Test
- @FlakyTest(detail = "Promote once confirmed non-flaky")
public void testStuckExitingWindow() {
final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
"closingWindow");
@@ -346,7 +343,6 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertNoStartingWindow(mToken);
}
- @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
@Test
public void testAddRemoveRace() {
// There was once a race condition between adding and removing starting windows
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 3f83caea613a..1e02a12e83db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -46,6 +46,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.view.IWindowManager;
@@ -71,6 +72,7 @@ import java.util.concurrent.TimeUnit;
* atest WmTests:AssistDataRequesterTest
*/
@MediumTest
+@Presubmit
public class AssistDataRequesterTest extends ActivityTestsBase {
private static final String TAG = AssistDataRequesterTest.class.getSimpleName();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 198e7ce63f52..b15e99aaa8c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -60,6 +60,7 @@ import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.After;
import org.junit.Before;
@@ -113,6 +114,7 @@ public class DisplayRotationTests {
public static void setUpOnce() {
sMockWm = mock(WindowManagerService.class);
sMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
+ sMockWm.mPolicy = mock(WindowManagerPolicy.class);
}
@Before
@@ -807,6 +809,8 @@ public class DisplayRotationTests {
mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
+ when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt()))
+ .thenReturn(WmDisplayCutout.NO_CUTOUT);
mMockDisplayPolicy = mock(DisplayPolicy.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java b/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java
index ce22788f7cb9..df26679dc1fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/KeyguardDisableHandlerTest.java
@@ -34,6 +34,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.util.SparseBooleanArray;
import com.android.server.wm.LockTaskController.LockTaskToken;
@@ -43,6 +44,7 @@ import org.junit.Test;
import java.lang.reflect.Constructor;
+@Presubmit
public class KeyguardDisableHandlerTest {
private KeyguardDisableHandler mKeyguardDisable;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index cc6a58a81635..a03d28b47057 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -40,7 +40,6 @@ import android.util.SparseBooleanArray;
import android.view.IRecentsAnimationRunner;
import android.view.SurfaceControl;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
@@ -112,7 +111,6 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
}
}
- @FlakyTest(bugId = 117117823)
@Test
public void testIncludedApps_expectTargetAndVisible() {
mWm.setRecentsAnimationController(mController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index c595868db484..2377df406fbc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -34,10 +34,12 @@ import static org.junit.Assert.assertTrue;
import android.app.IActivityTaskManager;
import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Before;
@@ -50,6 +52,8 @@ import org.junit.Test;
* atest WmTests:TaskPositionerTests
*/
@SmallTest
+@Presubmit
+@FlakyTest
public class TaskPositionerTests extends WindowTestsBase {
private static final boolean DEBUGGING = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
index 649b785c992b..99ceb2011db3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
@@ -31,6 +31,7 @@ import static org.junit.Assert.*;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
+import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
import org.junit.Before;
@@ -42,6 +43,7 @@ import org.junit.rules.ErrorCollector;
* Build/Install/Run:
* atest WmTests:CoordinateTransformsTest
*/
+@Presubmit
public class CoordinateTransformsTest {
private static final int W = 200;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index e99a289729a4..d5091680285b 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -291,6 +291,19 @@ public class TelecomManager {
"android.telecom.extra.OUTGOING_CALL_EXTRAS";
/**
+ * An optional boolean extra on {@link android.content.Intent#ACTION_CALL_EMERGENCY} to tell
+ * whether the user's dial intent is emergency; this is required to specify when the dialed
+ * number is ambiguous, identified as both emergency number and any other non-emergency number;
+ * e.g. in some situation, 611 could be both an emergency number in a country and a
+ * non-emergency number of a carrier's customer service hotline.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL =
+ "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
+
+ /**
* @hide
*/
public static final String EXTRA_UNKNOWN_CALL_HANDLE =
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index 53d69f447a56..24db438580c9 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -26,11 +26,12 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.location.LocationManager;
import android.os.Binder;
+import android.os.Build;
import android.os.Process;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.widget.Toast;
import java.util.List;
@@ -41,61 +42,236 @@ import java.util.List;
public final class LocationAccessPolicy {
private static final String TAG = "LocationAccessPolicy";
private static final boolean DBG = false;
+ public static final int MAX_SDK_FOR_ANY_ENFORCEMENT = Build.VERSION_CODES.P;
- /**
- * API to determine if the caller has permissions to get cell location.
- *
- * @param pkgName Package name of the application requesting access
- * @param uid The uid of the package
- * @param pid The pid of the package
- * @param throwOnDeniedPermission Whether to throw if the location permission is denied.
- * @return boolean true or false if permissions is granted
- */
- public static boolean canAccessCellLocation(@NonNull Context context, @NonNull String pkgName,
- int uid, int pid, boolean throwOnDeniedPermission) throws SecurityException {
- Trace.beginSection("TelephonyLocationCheck");
- try {
- // Always allow the phone process and system server to access location. This avoid
- // breaking legacy code that rely on public-facing APIs to access cell location, and
- // it doesn't create an info leak risk because the cell location is stored in the phone
- // process anyway, and the system server already has location access.
- if (uid == Process.PHONE_UID || uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
- return true;
+ public enum LocationPermissionResult {
+ ALLOWED,
+ /**
+ * Indicates that the denial is due to a transient device state
+ * (e.g. app-ops, location master switch)
+ */
+ DENIED_SOFT,
+ /**
+ * Indicates that the denial is due to a misconfigured app (e.g. missing entry in manifest)
+ */
+ DENIED_HARD,
+ }
+
+ public static class LocationPermissionQuery {
+ public final String callingPackage;
+ public final int callingUid;
+ public final int callingPid;
+ public final int minSdkVersionForCoarse;
+ public final int minSdkVersionForFine;
+ public final String method;
+
+ private LocationPermissionQuery(String callingPackage, int callingUid, int callingPid,
+ int minSdkVersionForCoarse, int minSdkVersionForFine, String method) {
+ this.callingPackage = callingPackage;
+ this.callingUid = callingUid;
+ this.callingPid = callingPid;
+ this.minSdkVersionForCoarse = minSdkVersionForCoarse;
+ this.minSdkVersionForFine = minSdkVersionForFine;
+ this.method = method;
+ }
+
+ public static class Builder {
+ private String mCallingPackage;
+ private int mCallingUid;
+ private int mCallingPid;
+ private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
+ private int mMinSdkVersionForFine = Integer.MAX_VALUE;
+ private String mMethod;
+
+ /**
+ * Mandatory parameter, used for performing permission checks.
+ */
+ public Builder setCallingPackage(String callingPackage) {
+ mCallingPackage = callingPackage;
+ return this;
}
- // We always require the location permission and also require the
- // location mode to be on for non-legacy apps. Legacy apps are
- // required to be in the foreground to at least mitigate the case
- // where a legacy app the user is not using tracks their location.
- // Granting ACCESS_FINE_LOCATION to an app automatically grants it
- // ACCESS_COARSE_LOCATION.
- if (throwOnDeniedPermission) {
- context.enforcePermission(Manifest.permission.ACCESS_COARSE_LOCATION,
- pid, uid, "canAccessCellLocation");
- } else if (context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION,
- pid, uid) == PackageManager.PERMISSION_DENIED) {
- if (DBG) Log.w(TAG, "Permission checked failed (" + pid + "," + uid + ")");
- return false;
+ /**
+ * Mandatory parameter, used for performing permission checks.
+ */
+ public Builder setCallingUid(int callingUid) {
+ mCallingUid = callingUid;
+ return this;
}
- final int opCode = AppOpsManager.permissionToOpCode(
- Manifest.permission.ACCESS_COARSE_LOCATION);
- if (opCode != AppOpsManager.OP_NONE && context.getSystemService(AppOpsManager.class)
- .noteOpNoThrow(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
- if (DBG) Log.w(TAG, "AppOp check failed (" + uid + "," + pkgName + ")");
- return false;
+
+ /**
+ * Mandatory parameter, used for performing permission checks.
+ */
+ public Builder setCallingPid(int callingPid) {
+ mCallingPid = callingPid;
+ return this;
}
- if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) {
- if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")");
- return false;
+
+ /**
+ * Apps that target at least this sdk version will be checked for coarse location
+ * permission. Defaults to INT_MAX (which means don't check)
+ */
+ public Builder setMinSdkVersionForCoarse(
+ int minSdkVersionForCoarse) {
+ mMinSdkVersionForCoarse = minSdkVersionForCoarse;
+ return this;
}
- // If the user or profile is current, permission is granted.
- // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
- return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context);
- } finally {
- Trace.endSection();
+
+ /**
+ * Apps that target at least this sdk version will be checked for fine location
+ * permission. Defaults to INT_MAX (which means don't check)
+ */
+ public Builder setMinSdkVersionForFine(
+ int minSdkVersionForFine) {
+ mMinSdkVersionForFine = minSdkVersionForFine;
+ return this;
+ }
+
+ /**
+ * Optional, for logging purposes only.
+ */
+ public Builder setMethod(String method) {
+ mMethod = method;
+ return this;
+ }
+
+ public LocationPermissionQuery build() {
+ return new LocationPermissionQuery(mCallingPackage, mCallingUid,
+ mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine, mMethod);
+ }
+ }
+ }
+
+ private static void logError(Context context, String errorMsg) {
+ Log.e(TAG, errorMsg);
+ try {
+ if (Build.IS_DEBUGGABLE) {
+ Toast.makeText(context, errorMsg, Toast.LENGTH_SHORT).show();
+ }
+ } catch (Throwable t) {
+ // whatever, not important
+ }
+ }
+
+ private static LocationPermissionResult appOpsModeToPermissionResult(int appOpsMode) {
+ switch (appOpsMode) {
+ case AppOpsManager.MODE_ALLOWED:
+ return LocationPermissionResult.ALLOWED;
+ case AppOpsManager.MODE_ERRORED:
+ return LocationPermissionResult.DENIED_HARD;
+ default:
+ return LocationPermissionResult.DENIED_SOFT;
}
}
+ private static LocationPermissionResult checkAppLocationPermissionHelper(Context context,
+ LocationPermissionQuery query, String permissionToCheck) {
+ String locationTypeForLog =
+ Manifest.permission.ACCESS_FINE_LOCATION.equals(permissionToCheck)
+ ? "fine" : "coarse";
+
+ // Do the app-ops and the manifest check without any of the allow-overrides first.
+ boolean hasManifestPermission = checkManifestPermission(context, query.callingPid,
+ query.callingUid, permissionToCheck);
+
+ int appOpMode = context.getSystemService(AppOpsManager.class)
+ .noteOpNoThrow(AppOpsManager.permissionToOpCode(permissionToCheck),
+ query.callingUid, query.callingPackage);
+
+ if (hasManifestPermission && appOpMode == AppOpsManager.MODE_ALLOWED) {
+ // If the app did everything right, return without logging.
+ return LocationPermissionResult.ALLOWED;
+ }
+
+ // If the app has the manifest permission but not the app-op permission, it means that
+ // it's aware of the requirement and the user denied permission explicitly. If we see
+ // this, don't let any of the overrides happen.
+ if (hasManifestPermission) {
+ Log.i(TAG, query.callingPackage + " is aware of " + locationTypeForLog + " but the"
+ + " app-ops permission is specifically denied.");
+ return appOpsModeToPermissionResult(appOpMode);
+ }
+
+ int minSdkVersion = Manifest.permission.ACCESS_FINE_LOCATION.equals(permissionToCheck)
+ ? query.minSdkVersionForFine : query.minSdkVersionForCoarse;
+
+ // If the app fails for some reason, see if it should be allowed to proceed.
+ if (minSdkVersion > MAX_SDK_FOR_ANY_ENFORCEMENT) {
+ String errorMsg = "Allowing " + query.callingPackage + " " + locationTypeForLog
+ + " because we're not enforcing API " + query.minSdkVersionForFine + " yet."
+ + " Please fix this app because it will break in the future. Called from "
+ + query.method;
+ logError(context, errorMsg);
+ return null;
+ } else if (!isAppAtLeastSdkVersion(context, query.callingPackage, minSdkVersion)) {
+ String errorMsg = "Allowing " + query.callingPackage + " " + locationTypeForLog
+ + " because it doesn't target API " + query.minSdkVersionForFine + " yet."
+ + " Please fix this app. Called from " + query.method;
+ logError(context, errorMsg);
+ return null;
+ } else {
+ // If we're not allowing it due to the above two conditions, this means that the app
+ // did not declare the permission in their manifest.
+ return LocationPermissionResult.DENIED_HARD;
+ }
+ }
+
+ public static LocationPermissionResult checkLocationPermission(
+ Context context, LocationPermissionQuery query) {
+ // Always allow the phone process and system server to access location. This avoid
+ // breaking legacy code that rely on public-facing APIs to access cell location, and
+ // it doesn't create an info leak risk because the cell location is stored in the phone
+ // process anyway, and the system server already has location access.
+ if (query.callingUid == Process.PHONE_UID || query.callingUid == Process.SYSTEM_UID
+ || query.callingUid == Process.ROOT_UID) {
+ return LocationPermissionResult.ALLOWED;
+ }
+
+ // Check the system-wide requirements. If the location master switch is off or
+ // the app's profile isn't in foreground, return a soft denial.
+ if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid)) {
+ return LocationPermissionResult.DENIED_SOFT;
+ }
+
+ // Do the check for fine, then for coarse.
+ if (query.minSdkVersionForFine < Integer.MAX_VALUE) {
+ LocationPermissionResult resultForFine = checkAppLocationPermissionHelper(
+ context, query, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (resultForFine != null) {
+ return resultForFine;
+ }
+ }
+
+ if (query.minSdkVersionForCoarse < Integer.MAX_VALUE) {
+ LocationPermissionResult resultForCoarse = checkAppLocationPermissionHelper(
+ context, query, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (resultForCoarse != null) {
+ return resultForCoarse;
+ }
+ }
+
+ // At this point, we're out of location checks to do. If the app bypassed all the previous
+ // ones due to the SDK grandfathering schemes, allow it access.
+ return LocationPermissionResult.ALLOWED;
+ }
+
+
+ private static boolean checkManifestPermission(Context context, int pid, int uid,
+ String permissionToCheck) {
+ return context.checkPermission(permissionToCheck, pid, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private static boolean checkSystemLocationAccess(@NonNull Context context, int uid, int pid) {
+ if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) {
+ if (DBG) Log.w(TAG, "Location disabled, failed, (" + uid + ")");
+ return false;
+ }
+ // If the user or profile is current, permission is granted.
+ // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
+ return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context, uid, pid);
+ }
+
private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
LocationManager locationManager = context.getSystemService(LocationManager.class);
if (locationManager == null) {
@@ -105,10 +281,10 @@ public final class LocationAccessPolicy {
return locationManager.isLocationEnabledForUser(UserHandle.of(userId));
}
- private static boolean checkInteractAcrossUsersFull(@NonNull Context context) {
- return context.checkCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
- == PackageManager.PERMISSION_GRANTED;
+ private static boolean checkInteractAcrossUsersFull(
+ @NonNull Context context, int pid, int uid) {
+ return checkManifestPermission(context, pid, uid,
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL);
}
private static boolean isCurrentProfile(@NonNull Context context, int uid) {
@@ -132,4 +308,18 @@ public final class LocationAccessPolicy {
Binder.restoreCallingIdentity(token);
}
}
-}
+
+ private static boolean isAppAtLeastSdkVersion(Context context, String pkgName, int sdkVersion) {
+ try {
+ if (context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion
+ >= sdkVersion) {
+ return true;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // In case of exception, assume known app (more strict checking)
+ // Note: This case will never happen since checkPackage is
+ // called to verify validity before checking app's version.
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index c37b492a9cf1..6e6d59e62148 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -152,7 +152,7 @@ public class NetworkRegistrationState implements Parcelable {
private final int[] mAvailableServices;
@Nullable
- private final CellIdentity mCellIdentity;
+ private CellIdentity mCellIdentity;
@Nullable
private VoiceSpecificRegistrationStates mVoiceSpecificStates;
@@ -521,4 +521,22 @@ public class NetworkRegistrationState implements Parcelable {
return new NetworkRegistrationState[size];
}
};
+
+ /**
+ * @hide
+ */
+ public NetworkRegistrationState sanitizeLocationInfo() {
+ NetworkRegistrationState result = copy();
+ result.mCellIdentity = null;
+ return result;
+ }
+
+ private NetworkRegistrationState copy() {
+ Parcel p = Parcel.obtain();
+ this.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ NetworkRegistrationState result = new NetworkRegistrationState(p);
+ p.recycle();
+ return result;
+ }
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 402763e52cfa..a1aee6d8217f 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -36,6 +36,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* Contains phone state and service related information.
@@ -1885,4 +1886,29 @@ public class ServiceState implements Parcelable {
? range1
: range2;
}
+
+ /**
+ * Returns a copy of self with location-identifying information removed.
+ * Always clears the NetworkRegistrationState's CellIdentity fields, but if removeCoarseLocation
+ * is true, clears other info as well.
+ * @hide
+ */
+ public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+ ServiceState state = new ServiceState(this);
+ if (state.mNetworkRegistrationStates != null) {
+ state.mNetworkRegistrationStates = state.mNetworkRegistrationStates.stream()
+ .map(NetworkRegistrationState::sanitizeLocationInfo)
+ .collect(Collectors.toList());
+ }
+ if (!removeCoarseLocation) return state;
+
+ state.mDataOperatorAlphaLong = null;
+ state.mDataOperatorAlphaShort = null;
+ state.mDataOperatorNumeric = null;
+ state.mVoiceOperatorAlphaLong = null;
+ state.mVoiceOperatorAlphaShort = null;
+ state.mVoiceOperatorNumeric = null;
+
+ return state;
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 109376f0f868..836a50bf05c7 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1864,7 +1864,7 @@ public class SubscriptionManager {
iSub.setDefaultSmsSubId(subscriptionId);
}
} catch (RemoteException ex) {
- // ignore it
+ ex.rethrowFromSystemServer();
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f9cf25319e99..ced4f4ab6573 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1698,10 +1698,7 @@ public class TelephonyManager {
* @deprecated use {@link #getAllCellInfo} instead, which returns a superset of this API.
*/
@Deprecated
- @RequiresPermission(anyOf = {
- android.Manifest.permission.ACCESS_COARSE_LOCATION,
- android.Manifest.permission.ACCESS_FINE_LOCATION
- })
+ @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
public CellLocation getCellLocation() {
try {
ITelephony telephony = getITelephony();
@@ -4951,7 +4948,7 @@ public class TelephonyManager {
* @return List of {@link android.telephony.CellInfo}; null if cell
* information is unavailable.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
public List<CellInfo> getAllCellInfo() {
try {
ITelephony telephony = getITelephony();
@@ -5028,7 +5025,7 @@ public class TelephonyManager {
* @param executor the executor on which callback will be invoked.
* @param callback a callback to receive CellInfo.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
public void requestCellInfoUpdate(
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
try {
@@ -5067,7 +5064,7 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ @RequiresPermission(allOf = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.MODIFY_PHONE_STATE})
public void requestCellInfoUpdate(@NonNull WorkSource workSource,
@NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
@@ -6657,9 +6654,10 @@ public class TelephonyManager {
*
* <p> Note that this scan can take a long time (sometimes minutes) to happen.
*
- * <p>Requires Permission:
+ * <p>Requires Permissions:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
* privileges (see {@link #hasCarrierPrivileges})
+ * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
*
* @return {@link CellNetworkScanResult} with the status
* {@link CellNetworkScanResult#STATUS_SUCCESS} and a list of
@@ -6668,12 +6666,15 @@ public class TelephonyManager {
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public CellNetworkScanResult getAvailableNetworks() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCellNetworkScanResults(getSubId());
+ return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
@@ -6692,7 +6693,8 @@ public class TelephonyManager {
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
- * app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * app has carrier privileges (see {@link #hasCarrierPrivileges})
+ * and {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param executor The executor through which the callback should be invoked. Since the scan
@@ -6703,7 +6705,10 @@ public class TelephonyManager {
* @return A NetworkScan obj which contains a callback which can be used to stop the scan.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ })
public NetworkScan requestNetworkScan(
NetworkScanRequest request, Executor executor,
TelephonyScanManager.NetworkScanCallback callback) {
@@ -6712,7 +6717,8 @@ public class TelephonyManager {
mTelephonyScanManager = new TelephonyScanManager();
}
}
- return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback);
+ return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
+ getOpPackageName());
}
/**
@@ -6722,7 +6728,10 @@ public class TelephonyManager {
* @removed
*/
@Deprecated
- @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ })
public NetworkScan requestNetworkScan(
NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
return requestNetworkScan(request, AsyncTask.SERIAL_EXECUTOR, callback);
@@ -8723,10 +8732,14 @@ public class TelephonyManager {
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
+ * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ Manifest.permission.READ_PHONE_STATE,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
}
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 96ff33255b53..91f74b867fa0 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -29,14 +29,14 @@ import android.os.Messenger;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.Log;
import android.util.SparseArray;
+
+import com.android.internal.telephony.ITelephony;
+
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
-import com.android.internal.telephony.ITelephony;
-
/**
* Manages the radio access network scan requests and callbacks.
*/
@@ -183,6 +183,7 @@ public final class TelephonyScanManager {
*
* <p>
* Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} and
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
@@ -192,11 +193,13 @@ public final class TelephonyScanManager {
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
- NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
+ NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
+ String callingPackage) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
+ int scanId = telephony.requestNetworkScan(
+ subId, request, mMessenger, new Binder(), callingPackage);
saveScanInfo(scanId, request, executor, callback);
return new NetworkScan(scanId, subId);
}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 59167b7d5bba..73f055649b3f 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -350,6 +350,9 @@ public final class ImsCallProfile implements Parcelable {
/** Indicates if the call is for testing purpose */
private boolean mEmergencyCallTesting = false;
+ /** Indicates if we have known the intent of the user for the call is emergency */
+ private boolean mHasKnownUserIntentEmergency = false;
+
/**
* Extras associated with this {@link ImsCallProfile}.
* <p>
@@ -789,12 +792,13 @@ public final class ImsCallProfile implements Parcelable {
*
* @hide
*/
- public void setEmergencyCallInfo(EmergencyNumber num) {
+ public void setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency) {
setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
setEmergencyUrns(num.getEmergencyUrns());
setEmergencyCallRouting(num.getEmergencyCallRouting());
setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
== EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
+ setHasKnownUserIntentEmergency(hasKnownUserIntentEmergency);
}
/**
@@ -860,6 +864,19 @@ public final class ImsCallProfile implements Parcelable {
}
/**
+ * Set if we have known the user intent of the call is emergency.
+ *
+ * This is only used to specify when the dialed number is ambiguous when it can be identified
+ * as both emergency number and any other non-emergency number; e.g. in some situation, 611
+ * could be both an emergency number in a country and a non-emergency number of a carrier's
+ * customer service hotline.
+ */
+ @VisibleForTesting
+ public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
+ mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
+ }
+
+ /**
* Get the emergency service categories, only valid if {@link #getServiceType} returns
* {@link #SERVICE_TYPE_EMERGENCY}
*
@@ -916,4 +933,16 @@ public final class ImsCallProfile implements Parcelable {
public boolean isEmergencyCallTesting() {
return mEmergencyCallTesting;
}
+
+ /**
+ * Checks if we have known the user intent of the call is emergency.
+ *
+ * This is only used to specify when the dialed number is ambiguous when it can be identified
+ * as both emergency number and any other non-emergency number; e.g. in some situation, 611
+ * could be both an emergency number in a country and a non-emergency number of a carrier's
+ * customer service hotline.
+ */
+ public boolean hasKnownUserIntentEmergency() {
+ return mHasKnownUserIntentEmergency;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index caa367fbaafe..7089ee5671c2 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -765,7 +765,7 @@ interface ITelephony {
* @param subId the id of the subscription.
* @return CellNetworkScanResult containing status of scan and networks.
*/
- CellNetworkScanResult getCellNetworkScanResults(int subId);
+ CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage);
/**
* Perform a radio network scan and return the id of this scan.
@@ -774,10 +774,11 @@ interface ITelephony {
* @param request Defines all the configs for network scan.
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
+ * @param callingPackage the calling package
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
- in IBinder binder);
+ in IBinder binder, in String callingPackage);
/**
* Stop an existing radio network scan.
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a7c95c78d05d..e57d838bcf92 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -3817,11 +3817,14 @@ public class ConnectivityServiceTest {
}
@Test
- public void testNattSocketKeepalives() throws Exception {
+ public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
executorSingleThread.shutdown();
+ }
+ @Test
+ public void testNattSocketKeepalives_InlineExecutor() throws Exception {
final Executor executorInline = (Runnable r) -> r.run();
doTestNattSocketKeepalivesWithExecutor(executorInline);
}
@@ -3963,6 +3966,7 @@ public class ConnectivityServiceTest {
testSocket2.close();
mWiFiNetworkAgent.disconnect();
+ waitFor(mWiFiNetworkAgent.getDisconnectedCV());
}
@Test
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 488de8789178..af9fdfbd364d 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -276,14 +276,19 @@ public class WifiInfo implements Parcelable {
/**
* Returns the service set identifier (SSID) of the current 802.11 network.
+ * <p>
* If the SSID can be decoded as UTF-8, it will be returned surrounded by double
- * quotation marks. Otherwise, it is returned as a string of hex digits. The
- * SSID may be &lt;unknown ssid&gt; if there is no network currently connected,
- * or if the caller has insufficient permissions to access the SSID.
- *
+ * quotation marks. Otherwise, it is returned as a string of hex digits.
+ * The SSID may be
+ * <lt>&lt;unknown ssid&gt;, if there is no network currently connected or if the caller has
+ * insufficient permissions to access the SSID.<lt>
+ * </p>
+ * <p>
* Prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method
* always returned the SSID with no quotes around it.
- * @return the SSID
+ * </p>
+ *
+ * @return the SSID.
*/
public String getSSID() {
if (mWifiSsid != null) {
@@ -312,7 +317,13 @@ public class WifiInfo implements Parcelable {
/**
* Return the basic service set identifier (BSSID) of the current access point.
- * The BSSID may be {@code null} if there is no network currently connected.
+ * <p>
+ * The BSSID may be
+ * <lt>{@code null}, if there is no network currently connected.</lt>
+ * <lt>{@code "02:00:00:00:00:00"}, if the caller has insufficient permissions to access the
+ * BSSID.<lt>
+ * </p>
+ *
* @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
*/
public String getBSSID() {
@@ -511,9 +522,13 @@ public class WifiInfo implements Parcelable {
/**
* Each configured network has a unique small integer ID, used to identify
- * the network when performing operations on the supplicant. This method
- * returns the ID for the currently connected network.
- * @return the network ID, or -1 if there is no currently connected network
+ * the network. This method returns the ID for the currently connected network.
+ * <p>
+ * The networkId may be {@code -1} if there is no currently connected network or if the caller
+ * has insufficient permissions to access the network ID.
+ * </p>
+ *
+ * @return the network ID.
*/
public int getNetworkId() {
return mNetworkId;