summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp13
-rw-r--r--api/current.txt3
-rw-r--r--api/system-current.txt6
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp10
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp18
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h7
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp10
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.h6
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp17
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h11
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp41
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h54
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp28
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h11
-rw-r--r--cmds/statsd/src/metrics/metrics_manager_util.cpp219
-rw-r--r--cmds/statsd/src/metrics/metrics_manager_util.h5
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp12
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp21
-rw-r--r--core/java/android/app/ActivityThread.java50
-rw-r--r--core/java/android/app/ApplicationPackageManager.java9
-rw-r--r--core/java/android/app/ContextImpl.java11
-rw-r--r--core/java/android/app/IApplicationThread.aidl1
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/content/pm/PackageManager.java11
-rw-r--r--core/java/android/content/pm/UserInfo.java2
-rw-r--r--core/java/android/service/euicc/EuiccService.java42
-rw-r--r--core/java/android/service/euicc/IEuiccService.aidl2
-rw-r--r--core/java/android/view/SurfaceControl.java158
-rw-r--r--core/java/android/view/SurfaceView.java127
-rw-r--r--core/java/com/android/internal/os/KernelWakelockReader.java16
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java4
-rw-r--r--location/java/android/location/LocationManager.java87
-rw-r--r--location/java/android/location/LocationProvider.java20
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java110
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp19
-rw-r--r--mime/Android.bp33
-rw-r--r--mime/java/android/content/type/DefaultMimeMapFactory.java63
-rw-r--r--packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java28
-rw-r--r--packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java210
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java75
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java387
-rw-r--r--packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java83
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java7
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java7
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java (renamed from core/java/android/content/pm/PackageManagerInternal.java)2
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java6
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java87
-rw-r--r--services/core/java/com/android/server/display/ColorFade.java14
-rw-r--r--services/core/java/com/android/server/integrity/model/EvaluationOutcome.java67
-rw-r--r--services/core/java/com/android/server/integrity/model/OpenFormula.java39
-rw-r--r--services/core/java/com/android/server/integrity/model/Rule.java2
-rw-r--r--services/core/java/com/android/server/pm/ComponentResolver.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageList.java (renamed from core/java/android/content/pm/PackageList.java)3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java53
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java6
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java42
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java37
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java2
-rw-r--r--services/core/java/com/android/server/wm/CircularDisplayMask.java53
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java24
-rw-r--r--services/core/java/com/android/server/wm/LaunchParamsPersister.java2
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java10
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java8
-rw-r--r--services/core/java/com/android/server/wm/SeamlessRotator.java5
-rw-r--r--services/core/java/com/android/server/wm/StrictModeFlash.java21
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java38
-rw-r--r--services/core/java/com/android/server/wm/Watermark.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java107
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DimmerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/StubTransaction.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java4
-rw-r--r--telephony/common/com/android/internal/telephony/SmsApplication.java (renamed from telephony/java/com/android/internal/telephony/SmsApplication.java)0
-rw-r--r--telephony/java/android/telephony/CellIdentity.java27
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java34
-rw-r--r--telephony/java/android/telephony/TelephonyScanManager.java22
-rw-r--r--telephony/java/android/telephony/euicc/EuiccManager.java36
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl12
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java2
-rw-r--r--telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/uicc/IccUtils.java30
-rw-r--r--tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java2
120 files changed, 2339 insertions, 993 deletions
diff --git a/Android.bp b/Android.bp
index a1061681358f..1eba3e2711f1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -953,6 +953,7 @@ stubs_defaults {
"test-base/src/**/*.java",
":opt-telephony-srcs",
":opt-net-voip-srcs",
+ ":core-current-stubs-source",
":core_public_api_files",
":updatable-media-srcs",
"test-mock/src/**/*.java",
@@ -1017,6 +1018,7 @@ stubs_defaults {
"core/java/**/*.logtags",
":opt-telephony-srcs",
":opt-net-voip-srcs",
+ ":core-current-stubs-source",
":core_public_api_files",
":updatable-media-srcs",
":jobscheduler-framework-source",
@@ -1570,3 +1572,14 @@ filegroup {
],
}
+// Avoid including Parcelable classes as we don't want to have two copies of
+// Parcelable cross the process.
+filegroup {
+ name: "framework-cellbroadcast-shared-srcs",
+ srcs: [
+ "core/java/android/util/LocalLog.java",
+ "core/java/android/util/Slog.java",
+ "core/java/com/android/internal/util/State.java",
+ "core/java/com/android/internal/util/StateMachine.java",
+ ],
+} \ No newline at end of file
diff --git a/api/current.txt b/api/current.txt
index 3a768ea98eb2..e6e2b40cbb19 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25387,6 +25387,7 @@ package android.media {
method public android.graphics.Bitmap getFrameAtIndex(int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
method public android.graphics.Bitmap getFrameAtIndex(int);
method public android.graphics.Bitmap getFrameAtTime(long, int);
+ method public android.graphics.Bitmap getFrameAtTime(long, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
method public android.graphics.Bitmap getFrameAtTime(long);
method public android.graphics.Bitmap getFrameAtTime();
method @NonNull public java.util.List<android.graphics.Bitmap> getFramesAtIndex(int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
@@ -25396,6 +25397,7 @@ package android.media {
method public android.graphics.Bitmap getPrimaryImage(@NonNull android.media.MediaMetadataRetriever.BitmapParams);
method public android.graphics.Bitmap getPrimaryImage();
method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int);
+ method public android.graphics.Bitmap getScaledFrameAtTime(long, int, int, int, @NonNull android.media.MediaMetadataRetriever.BitmapParams);
method public void release();
method public void setDataSource(String) throws java.lang.IllegalArgumentException;
method public void setDataSource(String, java.util.Map<java.lang.String,java.lang.String>) throws java.lang.IllegalArgumentException;
@@ -45170,6 +45172,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>);
method public boolean setLine1NumberForDisplay(String, String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index 8ed79a3f2338..4db7f4a537ec 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6557,7 +6557,8 @@ package android.service.euicc {
method public abstract int onDeleteSubscription(int, String);
method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
method @Deprecated public int onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean);
- method public abstract int onEraseSubscriptions(int);
+ method @Deprecated public abstract int onEraseSubscriptions(int);
+ method public int onEraseSubscriptionsWithOptions(int, @android.telephony.euicc.EuiccCardManager.ResetOption int);
method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean);
method public abstract String onGetEid(int);
@@ -8620,7 +8621,8 @@ package android.telephony.euicc {
public class EuiccManager {
method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle);
- method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptionsWithOptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus();
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 1d0d2fb70a9d..b5c8e35accad 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -37,6 +37,7 @@ using std::map;
using std::string;
using std::unordered_map;
using std::vector;
+using std::shared_ptr;
namespace android {
namespace os {
@@ -67,8 +68,13 @@ const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
CountMetricProducer::CountMetricProducer(const ConfigKey& key, const CountMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs)
- : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard) {
+ const int64_t timeBaseNs, const int64_t startTimeNs,
+ const unordered_map<int, shared_ptr<Activation>>&
+ eventActivationMap,
+ const unordered_map<int, vector<shared_ptr<Activation>>>&
+ eventDeactivationMap)
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+ eventDeactivationMap) {
if (metric.has_bucket()) {
mBucketSizeNs =
TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()) * 1000000;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index b4a910c6f410..61913c71cdcc 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -42,7 +42,11 @@ class CountMetricProducer : public MetricProducer {
public:
CountMetricProducer(const ConfigKey& key, const CountMetric& countMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int64_t timeBaseNs, const int64_t startTimeNs);
+ const int64_t timeBaseNs, const int64_t startTimeNs,
+ const std::unordered_map<int, std::shared_ptr<Activation>>&
+ eventActivationMap = {},
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap = {});
virtual ~CountMetricProducer();
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index d7b46d1858cc..31b90f3b13b1 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -36,6 +36,7 @@ using android::util::ProtoOutputStream;
using std::string;
using std::unordered_map;
using std::vector;
+using std::shared_ptr;
namespace android {
namespace os {
@@ -62,14 +63,15 @@ const int FIELD_ID_BUCKET_NUM = 4;
const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
-DurationMetricProducer::DurationMetricProducer(const ConfigKey& key, const DurationMetric& metric,
- const int conditionIndex, const size_t startIndex,
- const size_t stopIndex, const size_t stopAllIndex,
- const bool nesting,
- const sp<ConditionWizard>& wizard,
- const FieldMatcher& internalDimensions,
- const int64_t timeBaseNs, const int64_t startTimeNs)
- : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+DurationMetricProducer::DurationMetricProducer(
+ const ConfigKey& key, const DurationMetric& metric, const int conditionIndex,
+ const size_t startIndex, const size_t stopIndex, const size_t stopAllIndex,
+ const bool nesting, const sp<ConditionWizard>& wizard,
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs,
+ const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+ const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+ eventDeactivationMap),
mAggregationType(metric.aggregation_type()),
mStartIndex(startIndex),
mStopIndex(stopIndex),
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 56c9fd68eac5..0592b1808f52 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -42,7 +42,12 @@ public:
const int conditionIndex, const size_t startIndex,
const size_t stopIndex, const size_t stopAllIndex, const bool nesting,
const sp<ConditionWizard>& wizard,
- const FieldMatcher& internalDimensions, const int64_t timeBaseNs, const int64_t startTimeNs);
+ const FieldMatcher& internalDimensions, const int64_t timeBaseNs,
+ const int64_t startTimeNs,
+ const unordered_map<int, shared_ptr<Activation>>&
+ eventActivationMap = {},
+ const unordered_map<int, vector<shared_ptr<Activation>>>&
+ eventDeactivationMap = {});
virtual ~DurationMetricProducer();
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 96133bd0a38d..a60a9161bdbb 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -36,6 +36,7 @@ using std::map;
using std::string;
using std::unordered_map;
using std::vector;
+using std::shared_ptr;
namespace android {
namespace os {
@@ -54,8 +55,13 @@ const int FIELD_ID_ATOMS = 2;
EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric,
const int conditionIndex,
const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs)
- : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) {
+ const int64_t startTimeNs,
+ const unordered_map<int, shared_ptr<Activation>>&
+ eventActivationMap,
+ const unordered_map<int, vector<shared_ptr<Activation>>>&
+ eventDeactivationMap)
+ : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard, eventActivationMap,
+ eventDeactivationMap) {
if (metric.links().size() > 0) {
for (const auto& link : metric.links()) {
Metric2Condition mc;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 74e6bc845c04..aab53c8b6816 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -35,7 +35,11 @@ class EventMetricProducer : public MetricProducer {
public:
EventMetricProducer(const ConfigKey& key, const EventMetric& eventMetric,
const int conditionIndex, const sp<ConditionWizard>& wizard,
- const int64_t startTimeNs);
+ const int64_t startTimeNs,
+ const std::unordered_map<int, std::shared_ptr<Activation>>&
+ eventActivationMap = {},
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap = {});
virtual ~EventMetricProducer();
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index efd05dcb04f1..e409b6fbb9e9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -72,8 +72,11 @@ GaugeMetricProducer::GaugeMetricProducer(
const sp<ConditionWizard>& wizard, const int whatMatcherIndex,
const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int triggerAtomId,
const int atomId, const int64_t timeBaseNs, const int64_t startTimeNs,
- const sp<StatsPullerManager>& pullerManager)
- : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+ const sp<StatsPullerManager>& pullerManager,
+ const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+ const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard, eventActivationMap,
+ eventDeactivationMap),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
@@ -133,8 +136,11 @@ GaugeMetricProducer::GaugeMetricProducer(
mBucketSizeNs);
}
- // Adjust start for partial bucket
+ // Adjust start for partial first bucket and then pull if needed
mCurrentBucketStartTimeNs = startTimeNs;
+ if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
+ }
VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
(long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs,
@@ -295,11 +301,6 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
}
}
-void GaugeMetricProducer::prepareFirstBucketLocked() {
- if (mIsActive && mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs);
- }
-}
void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
bool triggerPuller = false;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index a612adf8a38b..dfe1d56c61c7 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -58,11 +58,14 @@ class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDa
public:
GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
- const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard,
+ const int whatMatcherIndex,const sp<EventMatcherWizard>& matcherWizard,
const int pullTagId, const int triggerAtomId, const int atomId,
const int64_t timeBaseNs, const int64_t startTimeNs,
- const sp<StatsPullerManager>& pullerManager);
+ const sp<StatsPullerManager>& pullerManager,
+ const std::unordered_map<int, std::shared_ptr<Activation>>&
+ eventActivationMap = {},
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap = {});
virtual ~GaugeMetricProducer();
@@ -125,8 +128,6 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- void prepareFirstBucketLocked() override;
-
void pullAndMatchEventsLocked(const int64_t timestampNs);
const int mWhatMatcherIndex;
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 1ab4fdf6e90c..3426a195a748 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -40,6 +40,29 @@ const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_ATOM_MATCHER_INDEX = 1;
const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_REMAINING_TTL_NANOS = 2;
const int FIELD_ID_ACTIVE_EVENT_ACTIVATION_STATE = 3;
+MetricProducer::MetricProducer(
+ const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
+ const int conditionIndex, const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap)
+ : mMetricId(metricId),
+ mConfigKey(key),
+ mTimeBaseNs(timeBaseNs),
+ mCurrentBucketStartTimeNs(timeBaseNs),
+ mCurrentBucketNum(0),
+ mCondition(initialCondition(conditionIndex)),
+ mConditionTrackerIndex(conditionIndex),
+ mConditionSliced(false),
+ mWizard(wizard),
+ mContainANYPositionInDimensionsInWhat(false),
+ mSliceByPositionALL(false),
+ mHasLinksToAllConditionDimensionsInTracker(false),
+ mEventActivationMap(eventActivationMap),
+ mEventDeactivationMap(eventDeactivationMap),
+ mIsActive(mEventActivationMap.empty()) {
+ }
+
void MetricProducer::onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event) {
if (!mIsActive) {
return;
@@ -97,24 +120,6 @@ void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) {
}
}
-void MetricProducer::addActivation(int activationTrackerIndex, const ActivationType& activationType,
- int64_t ttl_seconds, int deactivationTrackerIndex) {
- std::lock_guard<std::mutex> lock(mMutex);
- // When a metric producer does not depend on any activation, its mIsActive is true.
- // Therefore, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
- // change.
- if (mEventActivationMap.empty()) {
- mIsActive = false;
- }
- std::shared_ptr<Activation> activation =
- std::make_shared<Activation>(activationType, ttl_seconds * NS_PER_SEC);
- mEventActivationMap.emplace(activationTrackerIndex, activation);
- if (-1 != deactivationTrackerIndex) {
- auto& deactivationList = mEventDeactivationMap[deactivationTrackerIndex];
- deactivationList.push_back(activation);
- }
-}
-
void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs) {
auto it = mEventActivationMap.find(activationTrackerIndex);
if (it == mEventActivationMap.end()) {
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index fdbdc83fb66e..1e1eb69aa8f0 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -69,6 +69,19 @@ enum DumpLatency {
NO_TIME_CONSTRAINTS = 2
};
+struct Activation {
+ Activation(const ActivationType& activationType, const int64_t ttlNs)
+ : ttl_ns(ttlNs),
+ start_ns(0),
+ state(ActivationState::kNotActive),
+ activationType(activationType) {}
+
+ const int64_t ttl_ns;
+ int64_t start_ns;
+ ActivationState state;
+ const ActivationType activationType;
+};
+
// A MetricProducer is responsible for compute one single metrics, creating stats log report, and
// writing the report to dropbox. MetricProducers should respond to package changes as required in
// PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
@@ -76,21 +89,10 @@ enum DumpLatency {
class MetricProducer : public virtual PackageInfoListener {
public:
MetricProducer(const int64_t& metricId, const ConfigKey& key, const int64_t timeBaseNs,
- const int conditionIndex, const sp<ConditionWizard>& wizard)
- : mMetricId(metricId),
- mConfigKey(key),
- mTimeBaseNs(timeBaseNs),
- mCurrentBucketStartTimeNs(timeBaseNs),
- mCurrentBucketNum(0),
- mCondition(initialCondition(conditionIndex)),
- mConditionTrackerIndex(conditionIndex),
- mConditionSliced(false),
- mWizard(wizard),
- mContainANYPositionInDimensionsInWhat(false),
- mSliceByPositionALL(false),
- mHasLinksToAllConditionDimensionsInTracker(false),
- mIsActive(true) {
- }
+ const int conditionIndex, const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int, std::shared_ptr<Activation>>& eventActivationMap,
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap);
virtual ~MetricProducer(){};
@@ -188,11 +190,6 @@ public:
dropDataLocked(dropTimeNs);
}
- void prepareFirstBucket() {
- std::lock_guard<std::mutex> lock(mMutex);
- prepareFirstBucketLocked();
- }
-
void loadActiveMetric(const ActiveMetric& activeMetric, int64_t currentTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
loadActiveMetricLocked(activeMetric, currentTimeNs);
@@ -215,9 +212,6 @@ public:
void flushIfExpire(int64_t elapsedTimestampNs);
- void addActivation(int activationTrackerIndex, const ActivationType& activationType,
- int64_t ttl_seconds, int deactivationTrackerIndex = -1);
-
void writeActiveMetricToProtoOutputStream(
int64_t currentTimeNs, const DumpReportReason reason, ProtoOutputStream* proto);
@@ -310,7 +304,6 @@ protected:
virtual size_t byteSizeLocked() const = 0;
virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
virtual void dropDataLocked(const int64_t dropTimeNs) = 0;
- virtual void prepareFirstBucketLocked() {};
void loadActiveMetricLocked(const ActiveMetric& activeMetric, int64_t currentTimeNs);
void activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs);
void cancelEventActivationLocked(int deactivationTrackerIndex);
@@ -379,19 +372,6 @@ protected:
mutable std::mutex mMutex;
- struct Activation {
- Activation(const ActivationType& activationType, const int64_t ttlNs)
- : ttl_ns(ttlNs),
- start_ns(0),
- state(ActivationState::kNotActive),
- activationType(activationType) {}
-
- const int64_t ttl_ns;
- int64_t start_ns;
- ActivationState state;
- const ActivationType activationType;
- };
-
// When the metric producer has multiple activations, these activations are ORed to determine
// whether the metric producer is ready to generate metrics.
std::unordered_map<int, std::shared_ptr<Activation>> mEventActivationMap;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index bc1602497c39..7fe5a834f412 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -81,8 +81,11 @@ ValueMetricProducer::ValueMetricProducer(
const ConfigKey& key, const ValueMetric& metric, const int conditionIndex,
const sp<ConditionWizard>& conditionWizard, const int whatMatcherIndex,
const sp<EventMatcherWizard>& matcherWizard, const int pullTagId, const int64_t timeBaseNs,
- const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager)
- : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard),
+ const int64_t startTimeNs, const sp<StatsPullerManager>& pullerManager,
+ const unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+ const unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap)
+ : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard,
+ eventActivationMap, eventDeactivationMap),
mWhatMatcherIndex(whatMatcherIndex),
mEventMatcherWizard(matcherWizard),
mPullerManager(pullerManager),
@@ -108,7 +111,7 @@ ValueMetricProducer::ValueMetricProducer(
mMaxPullDelayNs(metric.max_pull_delay_sec() > 0 ? metric.max_pull_delay_sec() * NS_PER_SEC
: StatsdStats::kPullMaxDelayNs),
mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()),
- // Condition timer will be set in prepareFirstBucketLocked.
+ // Condition timer will be set later within the constructor after pulling events
mConditionTimer(false, timeBaseNs) {
int64_t bucketSizeMills = 0;
if (metric.has_bucket()) {
@@ -154,6 +157,15 @@ ValueMetricProducer::ValueMetricProducer(
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
mConditionTimer.newBucketStart(mCurrentBucketStartTimeNs);
+
+ // Kicks off the puller immediately if condition is true and diff based.
+ if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
+ pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
+ }
+ // Now that activations are processed, start the condition timer if needed.
+ mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
+ mCurrentBucketStartTimeNs);
+
VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
}
@@ -165,16 +177,6 @@ ValueMetricProducer::~ValueMetricProducer() {
}
}
-void ValueMetricProducer::prepareFirstBucketLocked() {
- // Kicks off the puller immediately if condition is true and diff based.
- if (mIsActive && mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
- pullAndMatchEventsLocked(mCurrentBucketStartTimeNs, mCondition);
- }
- // Now that activations are processed, start the condition timer if needed.
- mConditionTimer.onConditionChanged(mIsActive && mCondition == ConditionState::kTrue,
- mCurrentBucketStartTimeNs);
-}
-
void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 739f6ef07cc4..d7cd397da2c0 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -54,10 +54,13 @@ class ValueMetricProducer : public virtual MetricProducer, public virtual PullDa
public:
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
- const int whatMatcherIndex,
- const sp<EventMatcherWizard>& matcherWizard,
+ const int whatMatcherIndex, const sp<EventMatcherWizard>& matcherWizard,
const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
- const sp<StatsPullerManager>& pullerManager);
+ const sp<StatsPullerManager>& pullerManager,
+ const std::unordered_map<int, std::shared_ptr<Activation>>&
+ eventActivationMap = {},
+ const std::unordered_map<int, std::vector<std::shared_ptr<Activation>>>&
+ eventDeactivationMap = {});
virtual ~ValueMetricProducer();
@@ -116,8 +119,6 @@ private:
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
- void prepareFirstBucketLocked() override;
-
void dropDataLocked(const int64_t dropTimeNs) override;
// Calculate previous bucket end time based on current time.
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 40484f4fb86b..0fee71e1fe2c 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -18,6 +18,7 @@
#include "Log.h"
#include "metrics_manager_util.h"
+#include "MetricProducer.h"
#include "../condition/CombinationConditionTracker.h"
#include "../condition/SimpleConditionTracker.h"
@@ -137,6 +138,62 @@ bool handleMetricWithConditions(
return true;
}
+// Validates a metricActivation and populates state.
+// EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
+// to provide the producer with state about its activators and deactivators.
+// Returns false if there are errors.
+bool handleMetricActivation(
+ const StatsdConfig& config,
+ const int64_t metricId,
+ const int metricIndex,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ const unordered_map<int64_t, int>& logTrackerMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation,
+ unordered_map<int, shared_ptr<Activation>>& eventActivationMap,
+ unordered_map<int, vector<shared_ptr<Activation>>>& eventDeactivationMap) {
+ // Check if metric has an associated activation
+ auto itr = metricToActivationMap.find(metricId);
+ if (itr == metricToActivationMap.end()) return true;
+
+ int activationIndex = itr->second;
+ const MetricActivation& metricActivation = config.metric_activation(activationIndex);
+
+ for (int i = 0; i < metricActivation.event_activation_size(); i++) {
+ const EventActivation& activation = metricActivation.event_activation(i);
+
+ auto itr = logTrackerMap.find(activation.atom_matcher_id());
+ if (itr == logTrackerMap.end()) {
+ ALOGE("Atom matcher not found for event activation.");
+ return false;
+ }
+
+ ActivationType activationType = (activation.has_activation_type()) ?
+ activation.activation_type() : metricActivation.activation_type();
+ std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>(
+ activationType, activation.ttl_seconds() * NS_PER_SEC);
+
+ int atomMatcherIndex = itr->second;
+ activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
+ eventActivationMap.emplace(atomMatcherIndex, activationWrapper);
+
+ if (activation.has_deactivation_atom_matcher_id()) {
+ itr = logTrackerMap.find(activation.deactivation_atom_matcher_id());
+ if (itr == logTrackerMap.end()) {
+ ALOGE("Atom matcher not found for event deactivation.");
+ return false;
+ }
+ int deactivationAtomMatcherIndex = itr->second;
+ deactivationAtomTrackerToMetricMap[deactivationAtomMatcherIndex].push_back(metricIndex);
+ eventDeactivationMap[deactivationAtomMatcherIndex].push_back(activationWrapper);
+ }
+ }
+
+ metricsWithActivation.push_back(metricIndex);
+ return true;
+}
+
bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
unordered_map<int64_t, int>& logTrackerMap,
vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
@@ -293,16 +350,33 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
- unordered_map<int, std::vector<int>>& conditionToMetricMap,
- unordered_map<int, std::vector<int>>& trackerToMetricMap,
- unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
- config.event_metric_size() + config.value_metric_size();
+ config.event_metric_size() + config.gauge_metric_size() +
+ config.value_metric_size();
allMetricProducers.reserve(allMetricsCount);
StatsPullerManager statsPullerManager;
+ // Construct map from metric id to metric activation index. The map will be used to determine
+ // the metric activation corresponding to a metric.
+ unordered_map<int64_t, int> metricToActivationMap;
+ for (int i = 0; i < config.metric_activation_size(); i++) {
+ const MetricActivation& metricActivation = config.metric_activation(i);
+ int64_t metricId = metricActivation.metric_id();
+ if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
+ ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId);
+ return false;
+ }
+ metricToActivationMap.insert({metricId, i});
+ }
+
// Build MetricProducers for each metric defined in config.
// build CountMetricProducer
for (int i = 0; i < config.count_metric_size(); i++) {
@@ -337,8 +411,17 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- sp<MetricProducer> countProducer =
- new CountMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs);
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex,
+ metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+ eventDeactivationMap);
+ if (!success) return false;
+
+ sp<MetricProducer> countProducer = new CountMetricProducer(
+ key, metric, conditionIndex, wizard, timeBaseTimeNs, currentTimeNs,
+ eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(countProducer);
}
@@ -406,9 +489,18 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex,
+ metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+ eventDeactivationMap);
+ if (!success) return false;
+
sp<MetricProducer> durationMetric = new DurationMetricProducer(
key, metric, conditionIndex, trackerIndices[0], trackerIndices[1],
- trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs, currentTimeNs);
+ trackerIndices[2], nesting, wizard, internalDimensions, timeBaseTimeNs,
+ currentTimeNs, eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(durationMetric);
}
@@ -443,8 +535,17 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
- sp<MetricProducer> eventMetric =
- new EventMetricProducer(key, metric, conditionIndex, wizard, timeBaseTimeNs);
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex,
+ metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+ eventDeactivationMap);
+ if (!success) return false;
+
+ sp<MetricProducer> eventMetric = new EventMetricProducer(
+ key, metric, conditionIndex, wizard, timeBaseTimeNs, eventActivationMap,
+ eventDeactivationMap);
allMetricProducers.push_back(eventMetric);
}
@@ -500,9 +601,18 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex,
+ metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+ eventDeactivationMap);
+ if (!success) return false;
+
sp<MetricProducer> valueProducer = new ValueMetricProducer(
key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
- timeBaseTimeNs, currentTimeNs, pullerManager);
+ timeBaseTimeNs, currentTimeNs, pullerManager, eventActivationMap,
+ eventDeactivationMap);
allMetricProducers.push_back(valueProducer);
}
@@ -586,10 +696,19 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
}
}
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ bool success = handleMetricActivation(config, metric.id(), metricIndex,
+ metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
+ eventDeactivationMap);
+ if (!success) return false;
+
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
key, metric, conditionIndex, wizard,
trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
- timeBaseTimeNs, currentTimeNs, pullerManager);
+ timeBaseTimeNs, currentTimeNs, pullerManager,
+ eventActivationMap, eventDeactivationMap);
allMetricProducers.push_back(gaugeProducer);
}
for (int i = 0; i < config.no_report_metric_size(); ++i) {
@@ -707,73 +826,6 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
return true;
}
-bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
- const int64_t currentTimeNs,
- const unordered_map<int64_t, int> &logEventTrackerMap,
- const unordered_map<int64_t, int> &metricProducerMap,
- vector<sp<MetricProducer>>& allMetricProducers,
- unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
- unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
- vector<int>& metricsWithActivation) {
- for (int i = 0; i < config.metric_activation_size(); ++i) {
- const MetricActivation& metric_activation = config.metric_activation(i);
- auto itr = metricProducerMap.find(metric_activation.metric_id());
- if (itr == metricProducerMap.end()) {
- ALOGE("Metric id not found in metric activation: %lld",
- (long long)metric_activation.metric_id());
- return false;
- }
- const int metricTrackerIndex = itr->second;
- if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
- ALOGE("Invalid metric tracker index.");
- return false;
- }
- const sp<MetricProducer>& metric = allMetricProducers[metricTrackerIndex];
- metricsWithActivation.push_back(metricTrackerIndex);
- for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
- const EventActivation& activation = metric_activation.event_activation(j);
- auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
- if (logTrackerIt == logEventTrackerMap.end()) {
- ALOGE("Atom matcher not found for event activation.");
- return false;
- }
- const int atomMatcherIndex = logTrackerIt->second;
- activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
- metricTrackerIndex);
-
- ActivationType activationType;
- if (activation.has_activation_type()) {
- activationType = activation.activation_type();
- } else {
- activationType = metric_activation.activation_type();
- }
-
- if (activation.has_deactivation_atom_matcher_id()) {
- auto deactivationAtomMatcherIt =
- logEventTrackerMap.find(activation.deactivation_atom_matcher_id());
- if (deactivationAtomMatcherIt == logEventTrackerMap.end()) {
- ALOGE("Atom matcher not found for event deactivation.");
- return false;
- }
- const int deactivationMatcherIndex = deactivationAtomMatcherIt->second;
- deactivationAtomTrackerToMetricMap[deactivationMatcherIndex]
- .push_back(metricTrackerIndex);
- metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds(),
- deactivationMatcherIndex);
- } else {
- metric->addActivation(atomMatcherIndex, activationType, activation.ttl_seconds());
- }
- }
- }
- return true;
-}
-
-void prepareFirstBucket(const vector<sp<MetricProducer>>& allMetricProducers) {
- for (const auto& metric: allMetricProducers) {
- metric->prepareFirstBucket();
- }
-}
-
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -810,7 +862,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
if (!initMetrics(key, config, timeBaseNs, currentTimeNs, uidMap, pullerManager, logTrackerMap,
conditionTrackerMap, allAtomMatchers, allConditionTrackers, allMetricProducers,
conditionToMetricMap, trackerToMetricMap, metricProducerMap,
- noReportMetricIds)) {
+ noReportMetricIds, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
ALOGE("initMetricProducers failed");
return false;
}
@@ -824,14 +877,6 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
ALOGE("initAlarms failed");
return false;
}
- if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
- allMetricProducers, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
- ALOGE("initMetricActivations failed");
- return false;
- }
-
- prepareFirstBucket(allMetricProducers);
return true;
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index 3704969039c4..3802948f64da 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -91,7 +91,10 @@ bool initMetrics(
std::vector<sp<MetricProducer>>& allMetricProducers,
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
- std::set<int64_t>& noReportMetricIds);
+ std::set<int64_t>& noReportMetricIds,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 47c21aa8f1df..b027e8e687db 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -79,8 +79,6 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
logEventMatcherIndex, eventMatcherWizard,
-1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
pullerManager);
- gaugeProducer.prepareFirstBucket();
-
EXPECT_EQ(600500000000, gaugeProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, gaugeProducer.mCurrentBucketNum);
@@ -126,8 +124,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFirstBucket();
-
vector<shared_ptr<LogEvent>> allData;
allData.clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
@@ -211,7 +207,6 @@ TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
logEventMatcherIndex, eventMatcherWizard,
-1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
@@ -303,7 +298,6 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -370,7 +364,6 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
logEventMatcherIndex, eventMatcherWizard,
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
@@ -431,7 +424,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFirstBucket();
gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
@@ -521,7 +513,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- gaugeProducer.prepareFirstBucket();
gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
@@ -572,7 +563,6 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
logEventMatcherIndex, eventMatcherWizard,
tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFirstBucket();
Alert alert;
alert.set_id(101);
@@ -681,7 +671,6 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
logEventMatcherIndex, eventMatcherWizard,
tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
@@ -766,7 +755,6 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
logEventMatcherIndex, eventMatcherWizard,
tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- gaugeProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 2262c76e64f9..4b9d0c0ca718 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -105,7 +105,6 @@ class ValueMetricProducerTestHelper {
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer->prepareFirstBucket();
return valueProducer;
}
@@ -125,7 +124,6 @@ class ValueMetricProducerTestHelper {
new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer->prepareFirstBucket();
valueProducer->mCondition = ConditionState::kFalse;
return valueProducer;
}
@@ -169,7 +167,6 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
22, pullerManager);
- valueProducer.prepareFirstBucket();
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
@@ -199,7 +196,6 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
- valueProducer.prepareFirstBucket();
EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -381,7 +377,6 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, tagId,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer->prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -670,7 +665,6 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -728,7 +722,6 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -779,7 +772,6 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -854,7 +846,6 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -897,7 +888,6 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
@@ -972,7 +962,6 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
bucketStartTimeNs, bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
@@ -1269,7 +1258,6 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1314,7 +1302,6 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1361,7 +1348,6 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1412,7 +1398,6 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1458,7 +1443,6 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -1532,7 +1516,6 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
- valueProducer.prepareFirstBucket();
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -2081,7 +2064,6 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucket2StartTimeNs,
bucket2StartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
valueProducer.mCondition = ConditionState::kFalse;
// Event should be skipped since it is from previous bucket.
@@ -2862,7 +2844,6 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
@@ -2905,7 +2886,6 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -2969,7 +2949,6 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
eventMatcherWizard, tagId, bucketStartTimeNs,
bucketStartTimeNs, pullerManager);
- valueProducer.prepareFirstBucket();
ProtoOutputStream output;
std::set<string> strSet;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38aac1b47f65..7f27368e017e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1163,6 +1163,10 @@ public final class ActivityThread extends ClientTransactionHandler {
sendMessage(H.ATTACH_AGENT, agent);
}
+ public void attachStartupAgents(String dataDir) {
+ sendMessage(H.ATTACH_STARTUP_AGENTS, dataDir);
+ }
+
public void setSchedulingGroup(int group) {
// Note: do this immediately, since going into the foreground
// should happen regardless of what pending work we have to do
@@ -1812,6 +1816,7 @@ public final class ActivityThread extends ClientTransactionHandler {
public static final int EXECUTE_TRANSACTION = 159;
public static final int RELAUNCH_ACTIVITY = 160;
public static final int PURGE_RESOURCES = 161;
+ public static final int ATTACH_STARTUP_AGENTS = 162;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
@@ -1855,6 +1860,7 @@ public final class ActivityThread extends ClientTransactionHandler {
case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION";
case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
case PURGE_RESOURCES: return "PURGE_RESOURCES";
+ case ATTACH_STARTUP_AGENTS: return "ATTACH_STARTUP_AGENTS";
}
}
return Integer.toString(code);
@@ -2043,6 +2049,9 @@ public final class ActivityThread extends ClientTransactionHandler {
case PURGE_RESOURCES:
schedulePurgeIdler();
break;
+ case ATTACH_STARTUP_AGENTS:
+ handleAttachStartupAgents((String) msg.obj);
+ break;
}
Object obj = msg.obj;
if (obj instanceof SomeArgs) {
@@ -3779,6 +3788,27 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ static void handleAttachStartupAgents(String dataDir) {
+ try {
+ Path code_cache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
+ if (!Files.exists(code_cache)) {
+ return;
+ }
+ Path startup_path = code_cache.resolve("startup_agents");
+ if (Files.exists(startup_path)) {
+ for (Path p : Files.newDirectoryStream(startup_path)) {
+ handleAttachAgent(
+ p.toAbsolutePath().toString()
+ + "="
+ + dataDir,
+ null);
+ }
+ }
+ } catch (Exception e) {
+ // Ignored.
+ }
+ }
+
private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
/**
@@ -6427,26 +6457,6 @@ public final class ActivityThread extends ClientTransactionHandler {
NetworkSecurityConfigProvider.install(appContext);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- if (isAppDebuggable) {
- try {
- // Load all the agents in the code_cache/startup_agents directory.
- // We pass the absolute path to the data_dir as an argument.
- Path startup_path = appContext.getCodeCacheDir().toPath().resolve("startup_agents");
- if (Files.exists(startup_path)) {
- for (Path p : Files.newDirectoryStream(startup_path)) {
- handleAttachAgent(
- p.toAbsolutePath().toString()
- + "="
- + appContext.getDataDir().toPath().toAbsolutePath().toString(),
- data.info);
- }
- }
- } catch (Exception e) {
- // Ignored.
- }
- }
-
// Continue loading instrumentation.
if (ii != null) {
ApplicationInfo instrApp;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a2013075b379..86bf20a57eec 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3169,6 +3169,15 @@ public class ApplicationPackageManager extends PackageManager {
}
@Override
+ public String getSetupWizardPackageName() {
+ try {
+ return mPM.getSetupWizardPackageName();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ @Override
public String getIncidentReportApproverPackageName() {
try {
return mPM.getIncidentReportApproverPackageName();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ef23d5e7a424..5b211e147d64 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -741,12 +741,21 @@ class ContextImpl extends Context {
public File getCodeCacheDir() {
synchronized (mSync) {
if (mCodeCacheDir == null) {
- mCodeCacheDir = new File(getDataDir(), "code_cache");
+ mCodeCacheDir = getCodeCacheDirBeforeBind(getDataDir());
}
return ensurePrivateCacheDirExists(mCodeCacheDir, XATTR_INODE_CODE_CACHE);
}
}
+ /**
+ * Helper for getting code-cache dir potentially before application bind.
+ *
+ * @hide
+ */
+ static File getCodeCacheDirBeforeBind(File dataDir) {
+ return new File(dataDir, "code_cache");
+ }
+
@Override
public File getExternalCacheDir() {
// Operates on primary external storage
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index cfa065ba5bc9..51a64fff7c45 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -137,6 +137,7 @@ oneway interface IApplicationThread {
IVoiceInteractor voiceInteractor);
void handleTrustStorageUpdate();
void attachAgent(String path);
+ void attachStartupAgents(String dataDir);
void scheduleApplicationInfoChanged(in ApplicationInfo ai);
void setNetworkBlockSeq(long procStateSeq);
void scheduleTransaction(in ClientTransaction transaction);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4d7c43ace923..19d8edfa3884 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -686,6 +686,8 @@ interface IPackageManager {
String getSystemCaptionsServicePackageName();
+ String getSetupWizardPackageName();
+
String getIncidentReportApproverPackageName();
boolean isPackageStateProtected(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fd14d235a044..9513ce802813 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -7427,6 +7427,17 @@ public abstract class PackageManager {
}
/**
+ * @return the system defined setup wizard package name, or null if there's none.
+ *
+ * @hide
+ */
+ @Nullable
+ public String getSetupWizardPackageName() {
+ throw new UnsupportedOperationException(
+ "getSetupWizardPackageName not implemented in subclass");
+ }
+
+ /**
* @return the incident report approver app package name, or null if it's not defined
* by the OEM.
*
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 9f0bade9bd29..ccfa1843200c 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -350,7 +350,7 @@ public class UserInfo implements Parcelable {
@UnsupportedAppUsage
public UserHandle getUserHandle() {
- return new UserHandle(id);
+ return UserHandle.of(id);
}
@Override
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index ff8b13506201..8a9f68942e9d 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -15,6 +15,8 @@
*/
package android.service.euicc;
+import static android.telephony.euicc.EuiccCardManager.ResetOption;
+
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -503,7 +505,7 @@ public abstract class EuiccService extends Service {
String nickname);
/**
- * Erase all of the subscriptions on the device.
+ * Erase all operational subscriptions on the device.
*
* <p>This is intended to be used for device resets. As such, the reset should be performed even
* if an active SIM must be deactivated in order to access the eUICC.
@@ -512,10 +514,31 @@ public abstract class EuiccService extends Service {
* @return the result of the erase operation. May be one of the predefined {@code RESULT_}
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#eraseSubscriptions
+ *
+ * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
+ * and use @link{onEraseSubscriptionsWithOptions} instead
*/
+ @Deprecated
public abstract int onEraseSubscriptions(int slotId);
/**
+ * Erase specific subscriptions on the device.
+ *
+ * <p>This is intended to be used for device resets. As such, the reset should be performed even
+ * if an active SIM must be deactivated in order to access the eUICC.
+ *
+ * @param slotIndex index of the SIM slot to use for the operation.
+ * @param options flag for specific group of subscriptions to erase
+ * @return the result of the erase operation. May be one of the predefined {@code RESULT_}
+ * constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
+ * @see android.telephony.euicc.EuiccManager#eraseSubscriptionsWithOptions
+ */
+ public int onEraseSubscriptionsWithOptions(int slotIndex, @ResetOption int options) {
+ throw new UnsupportedOperationException(
+ "This method must be overridden to enable the ResetOption parameter");
+ }
+
+ /**
* Ensure that subscriptions will be retained on the next factory reset.
*
* <p>Called directly before a factory reset. Assumes that a normal factory reset will lead to
@@ -751,6 +774,23 @@ public abstract class EuiccService extends Service {
}
@Override
+ public void eraseSubscriptionsWithOptions(
+ int slotIndex, @ResetOption int options, IEraseSubscriptionsCallback callback) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ int result = EuiccService.this.onEraseSubscriptionsWithOptions(
+ slotIndex, options);
+ try {
+ callback.onComplete(result);
+ } catch (RemoteException e) {
+ // Can't communicate with the phone process; ignore.
+ }
+ }
+ });
+ }
+
+ @Override
public void retainSubscriptionsForFactoryReset(int slotId,
IRetainSubscriptionsForFactoryResetCallback callback) {
mExecutor.execute(new Runnable() {
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index c2cdf093706f..2acc47aae919 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -52,6 +52,8 @@ oneway interface IEuiccService {
void updateSubscriptionNickname(int slotId, String iccid, String nickname,
in IUpdateSubscriptionNicknameCallback callback);
void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
+ void eraseSubscriptionsWithOptions(
+ int slotIndex, int options, in IEraseSubscriptionsCallback callback);
void retainSubscriptionsForFactoryReset(
int slotId, in IRetainSubscriptionsForFactoryResetCallback callback);
} \ No newline at end of file
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b685cf098b33..6637c5b06a1b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -181,7 +181,6 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeSeverChildren(long transactionObj, long nativeObject);
private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
int scalingMode);
- private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
@@ -303,8 +302,8 @@ public final class SurfaceControl implements Parcelable {
/**
* Surface creation flag: Creates a Dim surface.
* Everything behind this surface is dimmed by the amount specified
- * in {@link #setAlpha}. It is an error to lock a Dim surface, since it
- * doesn't have a backing store.
+ * in {@link Transaction#setAlpha(SurfaceControl, float)}. It is an error to lock a Dim
+ * surface, since it doesn't have a backing store.
*
* @hide
*/
@@ -740,20 +739,20 @@ public final class SurfaceControl implements Parcelable {
* <p>
* Good practice is to first create the surface with the {@link #HIDDEN} flag
* specified, open a transaction, set the surface layer, layer stack, alpha,
- * and position, call {@link #show} if appropriate, and close the transaction.
+ * and position, call {@link Transaction#show(SurfaceControl)} if appropriate, and close the
+ * transaction.
* <p>
* Bounds of the surface is determined by its crop and its buffer size. If the
* surface has no buffer or crop, the surface is boundless and only constrained
* by the size of its parent bounds.
*
- * @param session The surface session, must not be null.
- * @param name The surface name, must not be null.
- * @param w The surface initial width.
- * @param h The surface initial height.
- * @param flags The surface creation flags. Should always include {@link #HIDDEN}
- * in the creation flags.
+ * @param session The surface session, must not be null.
+ * @param name The surface name, must not be null.
+ * @param w The surface initial width.
+ * @param h The surface initial height.
+ * @param flags The surface creation flags. Should always include {@link #HIDDEN}
+ * in the creation flags.
* @param metadata Initial metadata.
- *
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
*/
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
@@ -1014,15 +1013,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public void deferTransactionUntil(Surface barrier, long frame) {
- synchronized(SurfaceControl.class) {
- sGlobalTransaction.deferTransactionUntilSurface(this, barrier, frame);
- }
- }
-
- /**
- * @hide
- */
public void reparentChildren(SurfaceControl newParent) {
synchronized(SurfaceControl.class) {
sGlobalTransaction.reparentChildren(this, newParent);
@@ -1032,15 +1022,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public void reparent(SurfaceControl newParent) {
- synchronized(SurfaceControl.class) {
- sGlobalTransaction.reparent(this, newParent);
- }
- }
-
- /**
- * @hide
- */
public void detachChildren() {
synchronized(SurfaceControl.class) {
sGlobalTransaction.detachChildren(this);
@@ -1060,15 +1041,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public static void setAnimationTransaction() {
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setAnimationTransaction();
- }
- }
-
- /**
- * @hide
- */
@UnsupportedAppUsage
public void setLayer(int zorder) {
checkNotReleased();
@@ -1080,16 +1052,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public void setRelativeLayer(SurfaceControl relativeTo, int zorder) {
- checkNotReleased();
- synchronized(SurfaceControl.class) {
- sGlobalTransaction.setRelativeLayer(this, relativeTo, zorder);
- }
- }
-
- /**
- * @hide
- */
@UnsupportedAppUsage
public void setPosition(float x, float y) {
checkNotReleased();
@@ -1183,16 +1145,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public void setColor(@Size(3) float[] color) {
- checkNotReleased();
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setColor(this, color);
- }
- }
-
- /**
- * @hide
- */
public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
checkNotReleased();
synchronized(SurfaceControl.class) {
@@ -1201,36 +1153,6 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation matrix.
- *
- * @param matrix The matrix to apply.
- * @param float9 An array of 9 floats to be used to extract the values from the matrix.
- * @hide
- */
- public void setMatrix(Matrix matrix, float[] float9) {
- checkNotReleased();
- matrix.getValues(float9);
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setMatrix(this, float9[MSCALE_X], float9[MSKEW_Y],
- float9[MSKEW_X], float9[MSCALE_Y]);
- sGlobalTransaction.setPosition(this, float9[MTRANS_X], float9[MTRANS_Y]);
- }
- }
-
- /**
- * Sets the color transform for the Surface.
- * @param matrix A float array with 9 values represents a 3x3 transform matrix
- * @param translation A float array with 3 values represents a translation vector
- * @hide
- */
- public void setColorTransform(@Size(9) float[] matrix, @Size(3) float[] translation) {
- checkNotReleased();
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setColorTransform(this, matrix, translation);
- }
- }
-
- /**
* Sets the Surface to be color space agnostic. If a surface is color space agnostic,
* the color can be interpreted in any color space.
* @param agnostic A boolean to indicate whether the surface is color space agnostic
@@ -1260,43 +1182,6 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * Same as {@link SurfaceControl#setWindowCrop(Rect)} but sets the crop rect top left at 0, 0.
- *
- * @param width width of crop rect
- * @param height height of crop rect
- * @hide
- */
- public void setWindowCrop(int width, int height) {
- checkNotReleased();
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setWindowCrop(this, width, height);
- }
- }
-
- /**
- * Sets the corner radius of a {@link SurfaceControl}.
- *
- * @param cornerRadius Corner radius in pixels.
- * @hide
- */
- public void setCornerRadius(float cornerRadius) {
- checkNotReleased();
- synchronized (SurfaceControl.class) {
- sGlobalTransaction.setCornerRadius(this, cornerRadius);
- }
- }
-
- /**
- * @hide
- */
- public void setLayerStack(int layerStack) {
- checkNotReleased();
- synchronized(SurfaceControl.class) {
- sGlobalTransaction.setLayerStack(this, layerStack);
- }
- }
-
- /**
* @hide
*/
public void setOpaque(boolean isOpaque) {
@@ -2302,6 +2187,12 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Sets the transform and position of a {@link SurfaceControl} from a 3x3 transformation
+ * matrix.
+ *
+ * @param sc SurfaceControl to set matrix of
+ * @param matrix The matrix to apply.
+ * @param float9 An array of 9 floats to be used to extract the values from the matrix.
* @hide
*/
@UnsupportedAppUsage
@@ -2315,7 +2206,9 @@ public final class SurfaceControl implements Parcelable {
/**
* Sets the color transform for the Surface.
- * @param matrix A float array with 9 values represents a 3x3 transform matrix
+ *
+ * @param sc SurfaceControl to set color transform of
+ * @param matrix A float array with 9 values represents a 3x3 transform matrix
* @param translation A float array with 3 values represents a translation vector
* @hide
*/
@@ -2339,6 +2232,13 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Bounds the surface and its children to the bounds specified. Size of the surface will be
+ * ignored and only the crop and buffer size will be used to determine the bounds of the
+ * surface. If no crop is specified and the surface has no buffer, the surface bounds is
+ * only constrained by the size of its parent bounds.
+ *
+ * @param sc SurfaceControl to set crop of.
+ * @param crop Bounds of the crop to apply.
* @hide
*/
@UnsupportedAppUsage
@@ -2355,6 +2255,12 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Same as {@link Transaction#setWindowCrop(SurfaceControl, Rect)} but sets the crop rect
+ * top left at 0, 0.
+ *
+ * @param sc SurfaceControl to set crop of.
+ * @param width width of crop rect
+ * @param height height of crop rect
* @hide
*/
public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a85830009f58..2f0a4ebb84f8 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -418,12 +418,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
Log.d(TAG, System.identityHashCode(this)
+ " updateSurfaceAlpha: set alpha=" + alpha);
}
- SurfaceControl.openTransaction();
- try {
- mSurfaceControl.setAlpha(alpha);
- } finally {
- SurfaceControl.closeTransaction();
- }
+ mTmpTransaction.setAlpha(mSurfaceControl, alpha).apply();
}
mSurfaceAlpha = alpha;
}
@@ -701,17 +696,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
}
- private void updateBackgroundVisibilityInTransaction() {
+ private void updateBackgroundVisibility(Transaction t) {
if (mBackgroundControl == null) {
return;
}
if ((mSubLayer < 0) && ((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)) {
- mBackgroundControl.show();
+ t.show(mBackgroundControl);
} else {
- mBackgroundControl.hide();
+ t.hide(mBackgroundControl);
}
}
+
private void releaseSurfaces() {
mSurfaceAlpha = 1f;
@@ -853,61 +849,61 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Cur surface: " + mSurface);
- SurfaceControl.openTransaction();
- try {
- // If we are creating the surface control or the parent surface has not
- // changed, then set relative z. Otherwise allow the parent
- // SurfaceChangedCallback to update the relative z. This is needed so that
- // we do not change the relative z before the server is ready to swap the
- // parent surface.
- if (creating || (mParentSurfaceGenerationId
- == viewRoot.mSurface.getGenerationId())) {
- SurfaceControl.mergeToGlobalTransaction(updateRelativeZ());
- }
- mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId();
+ // If we are creating the surface control or the parent surface has not
+ // changed, then set relative z. Otherwise allow the parent
+ // SurfaceChangedCallback to update the relative z. This is needed so that
+ // we do not change the relative z before the server is ready to swap the
+ // parent surface.
+ if (creating || (mParentSurfaceGenerationId
+ == viewRoot.mSurface.getGenerationId())) {
+ updateRelativeZ(mTmpTransaction);
+ }
+ mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId();
- if (mViewVisibility) {
- mSurfaceControl.show();
- } else {
- mSurfaceControl.hide();
- }
- updateBackgroundVisibilityInTransaction();
- if (mUseAlpha) {
- mSurfaceControl.setAlpha(alpha);
- mSurfaceAlpha = alpha;
- }
+ if (mViewVisibility) {
+ mTmpTransaction.show(mSurfaceControl);
+ } else {
+ mTmpTransaction.hide(mSurfaceControl);
+ }
+ updateBackgroundVisibility(mTmpTransaction);
+ if (mUseAlpha) {
+ mTmpTransaction.setAlpha(mSurfaceControl, alpha);
+ mSurfaceAlpha = alpha;
+ }
- // While creating the surface, we will set it's initial
- // geometry. Outside of that though, we should generally
- // leave it to the RenderThread.
- //
- // There is one more case when the buffer size changes we aren't yet
- // prepared to sync (as even following the transaction applying
- // we still need to latch a buffer).
- // b/28866173
- if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
- mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
- mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
- 0.0f, 0.0f,
- mScreenRect.height() / (float) mSurfaceHeight);
- // Set a window crop when creating the surface or changing its size to
- // crop the buffer to the surface size since the buffer producer may
- // use SCALING_MODE_SCALE and submit a larger size than the surface
- // size.
- if (mClipSurfaceToBounds && mClipBounds != null) {
- mSurfaceControl.setWindowCrop(mClipBounds);
- } else {
- mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
- }
- }
- mSurfaceControl.setCornerRadius(mCornerRadius);
- if (sizeChanged && !creating) {
- mSurfaceControl.setBufferSize(mSurfaceWidth, mSurfaceHeight);
+ // While creating the surface, we will set it's initial
+ // geometry. Outside of that though, we should generally
+ // leave it to the RenderThread.
+ //
+ // There is one more case when the buffer size changes we aren't yet
+ // prepared to sync (as even following the transaction applying
+ // we still need to latch a buffer).
+ // b/28866173
+ if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
+ mTmpTransaction.setPosition(mSurfaceControl, mScreenRect.left,
+ mScreenRect.top);
+ mTmpTransaction.setMatrix(mSurfaceControl,
+ mScreenRect.width() / (float) mSurfaceWidth, 0.0f, 0.0f,
+ mScreenRect.height() / (float) mSurfaceHeight);
+ // Set a window crop when creating the surface or changing its size to
+ // crop the buffer to the surface size since the buffer producer may
+ // use SCALING_MODE_SCALE and submit a larger size than the surface
+ // size.
+ if (mClipSurfaceToBounds && mClipBounds != null) {
+ mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+ } else {
+ mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+ mSurfaceHeight);
}
- } finally {
- SurfaceControl.closeTransaction();
+ }
+ mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
+ if (sizeChanged && !creating) {
+ mTmpTransaction.setBufferSize(mSurfaceControl, mSurfaceWidth,
+ mSurfaceHeight);
}
+ mTmpTransaction.apply();
+
if (sizeChanged || creating) {
redrawNeeded = true;
}
@@ -1260,12 +1256,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
final float[] colorComponents = new float[] { Color.red(bgColor) / 255.f,
Color.green(bgColor) / 255.f, Color.blue(bgColor) / 255.f };
- SurfaceControl.openTransaction();
- try {
- mBackgroundControl.setColor(colorComponents);
- } finally {
- SurfaceControl.closeTransaction();
- }
+ mTmpTransaction.setColor(mBackgroundControl, colorComponents).apply();
}
@UnsupportedAppUsage
@@ -1480,15 +1471,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
@Override
public void surfaceReplaced(Transaction t) {
if (mSurfaceControl != null && mBackgroundControl != null) {
- t.merge(updateRelativeZ());
+ updateRelativeZ(t);
}
}
- private Transaction updateRelativeZ() {
- Transaction t = new Transaction();
+ private void updateRelativeZ(Transaction t) {
SurfaceControl viewRoot = getViewRootImpl().getSurfaceControl();
t.setRelativeLayer(mBackgroundControl, viewRoot, Integer.MIN_VALUE);
t.setRelativeLayer(mSurfaceControl, viewRoot, mSubLayer);
- return t;
}
}
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index e09e0e609380..cffb0ad9fdb9 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -29,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.FileInputStream;
+import java.util.Arrays;
import java.util.Iterator;
/**
@@ -66,6 +67,7 @@ public class KernelWakelockReader {
private final String[] mProcWakelocksName = new String[3];
private final long[] mProcWakelocksData = new long[3];
private ISuspendControlService mSuspendControlService = null;
+ private byte[] mKernelWakelockBuffer = new byte[32 * 1024];
/**
* Reads kernel wakelock stats and updates the staleStats with the new information.
@@ -84,7 +86,7 @@ public class KernelWakelockReader {
}
return removeOldStats(staleStats);
} else {
- byte[] buffer = new byte[32*1024];
+ Arrays.fill(mKernelWakelockBuffer, (byte) 0);
int len = 0;
boolean wakeup_sources;
final long startTime = SystemClock.uptimeMillis();
@@ -107,7 +109,8 @@ public class KernelWakelockReader {
}
int cnt;
- while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
+ while ((cnt = is.read(mKernelWakelockBuffer, len,
+ mKernelWakelockBuffer.length - len)) > 0) {
len += cnt;
}
@@ -125,12 +128,13 @@ public class KernelWakelockReader {
}
if (len > 0) {
- if (len >= buffer.length) {
- Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length);
+ if (len >= mKernelWakelockBuffer.length) {
+ Slog.wtf(TAG, "Kernel wake locks exceeded mKernelWakelockBuffer size "
+ + mKernelWakelockBuffer.length);
}
int i;
for (i=0; i<len; i++) {
- if (buffer[i] == '\0') {
+ if (mKernelWakelockBuffer[i] == '\0') {
len = i;
break;
}
@@ -143,7 +147,7 @@ public class KernelWakelockReader {
Slog.w(TAG, "Failed to get Native wakelock stats from SystemSuspend");
}
// Get kernel wakelock stats
- parseProcWakelocks(buffer, len, wakeup_sources, staleStats);
+ parseProcWakelocks(mKernelWakelockBuffer, len, wakeup_sources, staleStats);
return removeOldStats(staleStats);
}
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 0505fe30c55c..0feab7f61918 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -257,8 +257,6 @@ cc_library_shared {
"libnativeloader_lazy",
"libmemunreachable",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"libvintf",
"libnativewindow",
"libdl",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 18f8d7b04c3f..b030b33daf5e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -798,7 +798,7 @@
broadcast module. This is required in order to bind to the cell broadcast service, and
ensures that only the system can forward messages to it.
- <p>Protection level: signature|privileged
+ <p>Protection level: signature
@hide -->
<permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE"
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 51da0c871c4d..39bf7421b15e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -611,6 +611,10 @@ public class TransactionParcelTests {
}
@Override
+ public void attachStartupAgents(String s) throws RemoteException {
+ }
+
+ @Override
public void scheduleApplicationInfoChanged(ApplicationInfo applicationInfo)
throws RemoteException {
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f3d68755a513..90e29df45e51 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -145,7 +145,7 @@ public class LocationManager {
* Key used for an extra holding a boolean enabled/disabled status value when a provider
* enabled/disabled event is broadcast using a PendingIntent.
*
- * @see #requestLocationUpdates(String, long, long, PendingIntent)
+ * @see #requestLocationUpdates(String, long, float, PendingIntent)
*/
public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -153,7 +153,7 @@ public class LocationManager {
* Key used for an extra holding a {@link Location} value when a location change is broadcast
* using a PendingIntent.
*
- * @see #requestLocationUpdates(String, long, long, PendingIntent)
+ * @see #requestLocationUpdates(String, long, float, PendingIntent)
*/
public static final String KEY_LOCATION_CHANGED = "location";
@@ -1256,44 +1256,46 @@ public class LocationManager {
}
/**
- * Creates a mock location provider and adds it to the set of active providers.
+ * Creates a test location provider and adds it to the set of active providers. This provider
+ * will replace any provider with the same name that exists prior to this call.
*
- * @param name the provider name
+ * @param provider the provider name
*
+ * @throws IllegalArgumentException if provider is null
* @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
* mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
* allowed} for your app.
- * @throws IllegalArgumentException if a provider with the given name already exists
*/
public void addTestProvider(
- @NonNull String name, boolean requiresNetwork, boolean requiresSatellite,
+ @NonNull String provider, boolean requiresNetwork, boolean requiresSatellite,
boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+
ProviderProperties properties = new ProviderProperties(requiresNetwork,
requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed,
supportsBearing, powerRequirement, accuracy);
- if (name.matches(LocationProvider.BAD_CHARS_REGEX)) {
- throw new IllegalArgumentException("provider name contains illegal character: " + name);
- }
-
try {
- mService.addTestProvider(name, properties, mContext.getOpPackageName());
+ mService.addTestProvider(provider, properties, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Removes the mock location provider with the given name.
+ * Removes the test location provider with the given name or does nothing if no such test
+ * location provider exists.
*
* @param provider the provider name
*
+ * @throws IllegalArgumentException if provider is null
* @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
* mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
* allowed} for your app.
- * @throws IllegalArgumentException if no provider with the given name exists
*/
public void removeTestProvider(@NonNull String provider) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+
try {
mService.removeTestProvider(provider, mContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1302,60 +1304,53 @@ public class LocationManager {
}
/**
- * Sets a mock location for the given provider.
- * <p>This location will be used in place of any actual location from the provider.
- * The location object must have a minimum number of fields set to be
- * considered a valid LocationProvider Location, as per documentation
- * on {@link Location} class.
+ * Sets a new location for the given test provider. This location will be identiable as a mock
+ * location to all clients via {@link Location#isFromMockProvider()}.
+ *
+ * <p>The location object must have a minimum number of fields set to be considered valid, as
+ * per documentation on {@link Location} class.
*
* @param provider the provider name
- * @param loc the mock location
+ * @param location the mock location
*
* @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
* mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
* allowed} for your app.
- * @throws IllegalArgumentException if no provider with the given name exists
- * @throws IllegalArgumentException if the location is incomplete
+ * @throws IllegalArgumentException if the provider is null or not a test provider
+ * @throws IllegalArgumentException if the location is null or incomplete
*/
- public void setTestProviderLocation(@NonNull String provider, @NonNull Location loc) {
- if (!loc.isComplete()) {
+ public void setTestProviderLocation(@NonNull String provider, @NonNull Location location) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+ Preconditions.checkArgument(location != null, "invalid null location");
+
+ if (!location.isComplete()) {
IllegalArgumentException e = new IllegalArgumentException(
- "Incomplete location object, missing timestamp or accuracy? " + loc);
+ "Incomplete location object, missing timestamp or accuracy? " + location);
if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
- // just log on old platform (for backwards compatibility)
Log.w(TAG, e);
- loc.makeComplete();
+ location.makeComplete();
} else {
- // really throw it!
throw e;
}
}
try {
- mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
+ mService.setTestProviderLocation(provider, location, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Removes any mock location associated with the given provider.
- *
- * @param provider the provider name
+ * Does nothing.
*
- * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
- * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
- * allowed} for your app.
- * @throws IllegalArgumentException if no provider with the given name exists
- *
- * @deprecated This function has always been a no-op, and may be removed in the future.
+ * @deprecated This method has always been a no-op, and may be removed in the future.
*/
@Deprecated
public void clearTestProviderLocation(@NonNull String provider) {}
/**
- * Sets a mock enabled value for the given provider. This value will be used in place
- * of any actual value from the provider.
+ * Sets the given test provider to be enabled or disabled.
*
* @param provider the provider name
* @param enabled the mock enabled value
@@ -1363,9 +1358,11 @@ public class LocationManager {
* @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
* mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
* allowed} for your app.
- * @throws IllegalArgumentException if no provider with the given name exists
+ * @throws IllegalArgumentException if provider is null or not a test provider
*/
public void setTestProviderEnabled(@NonNull String provider, boolean enabled) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+
try {
mService.setTestProviderEnabled(provider, enabled, mContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1374,14 +1371,8 @@ public class LocationManager {
}
/**
- * Removes any mock enabled value associated with the given provider.
- *
- * @param provider the provider name
- *
- * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
- * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
- * allowed} for your app.
- * @throws IllegalArgumentException if no provider with the given name exists
+ * Equivalent to calling {@link #setTestProviderEnabled(String, boolean)} to disable a test
+ * provider.
*
* @deprecated Use {@link #setTestProviderEnabled(String, boolean)} instead.
*/
diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java
index b69a9d79e5b8..52a03b61d21c 100644
--- a/location/java/android/location/LocationProvider.java
+++ b/location/java/android/location/LocationProvider.java
@@ -53,28 +53,10 @@ public class LocationProvider {
@Deprecated
public static final int AVAILABLE = 2;
- /**
- * A regular expression matching characters that may not appear
- * in the name of a LocationProvider
- * @hide
- */
- public static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]";
-
private final String mName;
private final ProviderProperties mProperties;
- /**
- * Constructs a LocationProvider with the given name. Provider names must
- * consist only of the characters [a-zA-Z0-9].
- *
- * @throws IllegalArgumentException if name contains an illegal character
- *
- * @hide
- */
- public LocationProvider(String name, ProviderProperties properties) {
- if (name.matches(BAD_CHARS_REGEX)) {
- throw new IllegalArgumentException("provider name contains illegal character: " + name);
- }
+ LocationProvider(String name, ProviderProperties properties) {
mName = name;
mProperties = properties;
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 0346010f4587..f421029909bd 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -227,6 +227,44 @@ public class MediaMetadataRetriever implements AutoCloseable {
public native String extractMetadata(int keyCode);
/**
+ * This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
+ * except that the device will choose the actual {@link Bitmap.Config} to use.
+ *
+ * @param timeUs The time position where the frame will be retrieved.
+ * When retrieving the frame at the given time position, there is no
+ * guarantee that the data source has a frame located at the position.
+ * When this happens, a frame nearby will be returned. If timeUs is
+ * negative, time position and option will ignored, and any frame
+ * that the implementation considers as representative may be returned.
+ *
+ * @param option a hint on how the frame is found. Use
+ * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp earlier than or the same as timeUs. Use
+ * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp later than or the same as timeUs. Use
+ * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp closest to or the same as timeUs. Use
+ * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
+ * or may not be a sync frame but is closest to or the same as timeUs.
+ * {@link #OPTION_CLOSEST} often has larger performance overhead compared
+ * to the other options if there is no sync frame located at timeUs.
+ *
+ * @return A Bitmap containing a representative video frame, which can be null,
+ * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can
+ * be used to query the actual {@link Bitmap.Config}.
+ *
+ * @see {@link #getFrameAtTime(long, int, BitmapParams)}
+ */
+ public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+ if (option < OPTION_PREVIOUS_SYNC ||
+ option > OPTION_CLOSEST) {
+ throw new IllegalArgumentException("Unsupported option: " + option);
+ }
+
+ return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, null);
+ }
+
+ /**
* Call this method after setDataSource(). This method finds a
* representative frame close to the given time position by considering
* the given option if possible, and returns it as a bitmap.
@@ -255,16 +293,60 @@ public class MediaMetadataRetriever implements AutoCloseable {
* {@link #OPTION_CLOSEST} often has larger performance overhead compared
* to the other options if there is no sync frame located at timeUs.
*
+ * @param params BitmapParams that controls the returned bitmap config
+ * (such as pixel formats).
+ *
* @return A Bitmap containing a representative video frame, which
* can be null, if such a frame cannot be retrieved.
+ *
+ * @see {@link #getFrameAtTime(long, int)}
*/
- public Bitmap getFrameAtTime(long timeUs, @Option int option) {
+ public Bitmap getFrameAtTime(
+ long timeUs, @Option int option, @NonNull BitmapParams params) {
if (option < OPTION_PREVIOUS_SYNC ||
option > OPTION_CLOSEST) {
throw new IllegalArgumentException("Unsupported option: " + option);
}
- return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/);
+ return _getFrameAtTime(timeUs, option, -1 /*dst_width*/, -1 /*dst_height*/, params);
+ }
+
+ /**
+ * This method is similar to {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
+ * except that the device will choose the actual {@link Bitmap.Config} to use.
+ *
+ * @param timeUs The time position in microseconds where the frame will be retrieved.
+ * When retrieving the frame at the given time position, there is no
+ * guarantee that the data source has a frame located at the position.
+ * When this happens, a frame nearby will be returned. If timeUs is
+ * negative, time position and option will ignored, and any frame
+ * that the implementation considers as representative may be returned.
+ *
+ * @param option a hint on how the frame is found. Use
+ * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp earlier than or the same as timeUs. Use
+ * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp later than or the same as timeUs. Use
+ * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+ * that has a timestamp closest to or the same as timeUs. Use
+ * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
+ * or may not be a sync frame but is closest to or the same as timeUs.
+ * {@link #OPTION_CLOSEST} often has larger performance overhead compared
+ * to the other options if there is no sync frame located at timeUs.
+ *
+ * @param dstWidth expected output bitmap width
+ * @param dstHeight expected output bitmap height
+ * @return A Bitmap containing a representative video frame, which can be null,
+ * if such a frame cannot be retrieved. {@link Bitmap#getConfig()} can
+ * be used to query the actual {@link Bitmap.Config}.
+ * @throws IllegalArgumentException if passed in invalid option or width by height
+ * is less than or equal to 0.
+ * @see {@link #getScaledFrameAtTime(long, int, int, int, BitmapParams)}
+ */
+ public Bitmap getScaledFrameAtTime(
+ long timeUs, @Option int option, int dstWidth, int dstHeight) {
+ validate(option, dstWidth, dstHeight);
+ return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, null);
}
/**
@@ -297,15 +379,23 @@ public class MediaMetadataRetriever implements AutoCloseable {
*
* @param dstWidth expected output bitmap width
* @param dstHeight expected output bitmap height
+ * @param params BitmapParams that controls the returned bitmap config
+ * (such as pixel formats).
+ *
* @return A Bitmap of size not larger than dstWidth by dstHeight containing a
* scaled video frame, which can be null, if such a frame cannot be retrieved.
* @throws IllegalArgumentException if passed in invalid option or width by height
* is less than or equal to 0.
+ * @see {@link #getScaledFrameAtTime(long, int, int, int)}
*/
- public Bitmap getScaledFrameAtTime(
- long timeUs, @Option int option, int dstWidth, int dstHeight) {
- if (option < OPTION_PREVIOUS_SYNC ||
- option > OPTION_CLOSEST) {
+ public Bitmap getScaledFrameAtTime(long timeUs, @Option int option,
+ int dstWidth, int dstHeight, @NonNull BitmapParams params) {
+ validate(option, dstWidth, dstHeight);
+ return _getFrameAtTime(timeUs, option, dstWidth, dstHeight, params);
+ }
+
+ private void validate(@Option int option, int dstWidth, int dstHeight) {
+ if (option < OPTION_PREVIOUS_SYNC || option > OPTION_CLOSEST) {
throw new IllegalArgumentException("Unsupported option: " + option);
}
if (dstWidth <= 0) {
@@ -314,8 +404,6 @@ public class MediaMetadataRetriever implements AutoCloseable {
if (dstHeight <= 0) {
throw new IllegalArgumentException("Invalid height: " + dstHeight);
}
-
- return _getFrameAtTime(timeUs, option, dstWidth, dstHeight);
}
/**
@@ -365,10 +453,12 @@ public class MediaMetadataRetriever implements AutoCloseable {
* @see #getFrameAtTime(long, int)
*/
public Bitmap getFrameAtTime() {
- return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/);
+ return _getFrameAtTime(
+ -1, OPTION_CLOSEST_SYNC, -1 /*dst_width*/, -1 /*dst_height*/, null);
}
- private native Bitmap _getFrameAtTime(long timeUs, int option, int width, int height);
+ private native Bitmap _getFrameAtTime(
+ long timeUs, int option, int width, int height, @Nullable BitmapParams params);
public static final class BitmapParams {
private Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 18fd1a01cfd6..bc4bcebaf560 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -350,9 +350,10 @@ static jobject getBitmapFromVideoFrame(
return jBitmap;
}
-static int getColorFormat(JNIEnv *env, jobject options) {
+static int getColorFormat(JNIEnv *env, jobject options,
+ int defaultPreferred = HAL_PIXEL_FORMAT_RGBA_8888) {
if (options == NULL) {
- return HAL_PIXEL_FORMAT_RGBA_8888;
+ return defaultPreferred;
}
ScopedLocalRef<jobject> inConfig(env, env->GetObjectField(options, fields.inPreferredConfig));
@@ -383,7 +384,8 @@ static SkColorType setOutColorType(JNIEnv *env, int colorFormat, jobject options
}
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
- JNIEnv *env, jobject thiz, jlong timeUs, jint option, jint dst_width, jint dst_height)
+ JNIEnv *env, jobject thiz, jlong timeUs, jint option,
+ jint dst_width, jint dst_height, jobject params)
{
ALOGV("getFrameAtTime: %lld us option: %d dst width: %d heigh: %d",
(long long)timeUs, option, dst_width, dst_height);
@@ -392,10 +394,13 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return NULL;
}
+ // For getFrameAtTime family of calls, default to HAL_PIXEL_FORMAT_RGB_565
+ // to keep the behavior consistent with older releases
+ int colorFormat = getColorFormat(env, params, HAL_PIXEL_FORMAT_RGB_565);
// Call native method to retrieve a video frame
VideoFrame *videoFrame = NULL;
- sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option);
+ sp<IMemory> frameMemory = retriever->getFrameAtTime(timeUs, option, colorFormat);
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
@@ -408,7 +413,9 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(
return NULL;
}
- return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, kRGB_565_SkColorType);
+ SkColorType outColorType = setOutColorType(env, colorFormat, params);
+
+ return getBitmapFromVideoFrame(env, videoFrame, dst_width, dst_height, outColorType);
}
static jobject android_media_MediaMetadataRetriever_getImageAtIndex(
@@ -739,7 +746,7 @@ static const JNINativeMethod nativeMethods[] = {
(void *)android_media_MediaMetadataRetriever_setDataSourceFD},
{"_setDataSource", "(Landroid/media/MediaDataSource;)V",
(void *)android_media_MediaMetadataRetriever_setDataSourceCallback},
- {"_getFrameAtTime", "(JIII)Landroid/graphics/Bitmap;",
+ {"_getFrameAtTime", "(JIIILandroid/media/MediaMetadataRetriever$BitmapParams;)Landroid/graphics/Bitmap;",
(void *)android_media_MediaMetadataRetriever_getFrameAtTime},
{
"_getImageAtIndex",
diff --git a/mime/Android.bp b/mime/Android.bp
index 8b2b05958b6f..23a8fbf5059c 100644
--- a/mime/Android.bp
+++ b/mime/Android.bp
@@ -60,7 +60,7 @@ java_genrule {
tools: [
"soong_zip",
],
- srcs: [":mime.types"],
+ srcs: [":mime.types.minimized"],
out: ["mimemap-res.jar"],
cmd: "mkdir $(genDir)/res/ && cp $(in) $(genDir)/res/ && $(location soong_zip) -C $(genDir) -o $(out) -D $(genDir)/res/",
}
@@ -73,42 +73,49 @@ java_genrule {
tools: [
"soong_zip",
],
- srcs: [":mime.types"],
+ srcs: [":mime.types.minimized"],
out: ["mimemap-testing-res.jar"],
cmd: "mkdir $(genDir)/testres/ && cp $(in) $(genDir)/testres/ && $(location soong_zip) -C $(genDir) -o $(out) -D $(genDir)/testres/",
}
-// Combination of all *mime.types resources.
+// Combination of all *mime.types.minimized resources.
filegroup {
- name: "mime.types",
+ name: "mime.types.minimized",
visibility: [
"//visibility:private",
],
srcs: [
- ":debian.mime.types",
- ":android.mime.types",
- ":vendor.mime.types",
+ ":debian.mime.types.minimized",
+ ":android.mime.types.minimized",
+ ":vendor.mime.types.minimized",
],
}
-filegroup {
- name: "android.mime.types",
+java_genrule {
+ name: "android.mime.types.minimized",
visibility: [
"//visibility:private",
],
- path: "java-res/",
+ out: ["android.mime.types"],
srcs: [
"java-res/android.mime.types",
],
+ // strip comments normalize whitepace drop empty lines
+ cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | grep ' ' > $(out)",
}
-filegroup {
- name: "vendor.mime.types",
+// Unlike the other *mime.types files, vendor.mime.types gets '?' prepended to
+// every field so that its mappings will never overwrite earlier mappings by
+// the other resource files. http://b/141842825
+java_genrule {
+ name: "vendor.mime.types.minimized",
visibility: [
"//visibility:private",
],
- path: "java-res/",
+ out: ["vendor.mime.types"],
srcs: [
"java-res/vendor.mime.types",
],
+ // strip comments normalize whitepace drop empty lines prepend ? to fields that are missing it
+ cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | grep ' ' | awk '{for(i=1;i<=NF;i++) { sub(/^\\??/, \"?\", $$i); }; print}' > $(out)",
}
diff --git a/mime/java/android/content/type/DefaultMimeMapFactory.java b/mime/java/android/content/type/DefaultMimeMapFactory.java
index 03b685df644e..11d20d4d6c80 100644
--- a/mime/java/android/content/type/DefaultMimeMapFactory.java
+++ b/mime/java/android/content/type/DefaultMimeMapFactory.java
@@ -23,11 +23,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
-import java.util.regex.Pattern;
/**
* Creates the framework default {@link MimeMap}, a bidirectional mapping
@@ -53,8 +51,6 @@ public class DefaultMimeMapFactory {
return create(resourceName -> c.getResourceAsStream("/res/" + resourceName));
}
- private static final Pattern SPLIT_PATTERN = Pattern.compile("\\s+");
-
/**
* Creates a {@link MimeMap} instance whose resources are loaded from the
* InputStreams looked up in {@code resourceSupplier}.
@@ -63,33 +59,43 @@ public class DefaultMimeMapFactory {
*/
public static MimeMap create(Function<String, InputStream> resourceSupplier) {
MimeMap.Builder builder = MimeMap.builder();
- parseTypes(builder, true, resourceSupplier, "mime.types");
- parseTypes(builder, true, resourceSupplier, "android.mime.types");
- parseTypes(builder, false, resourceSupplier, "vendor.mime.types");
+ // The files loaded here must be in minimized format with lines of the
+ // form "mime/type ext1 ext2 ext3", i.e. no comments, no empty lines, no
+ // leading/trailing whitespace and with a single space between entries on
+ // each line. See http://b/142267887
+ //
+ // Note: the order here matters - later entries can overwrite earlier ones
+ // (except that vendor.mime.types entries are prefixed with '?' which makes
+ // them never overwrite).
+ parseTypes(builder, resourceSupplier, "debian.mime.types");
+ parseTypes(builder, resourceSupplier, "android.mime.types");
+ parseTypes(builder, resourceSupplier, "vendor.mime.types");
return builder.build();
}
- private static void parseTypes(MimeMap.Builder builder, boolean allowOverwrite,
+ private static void parseTypes(MimeMap.Builder builder,
Function<String, InputStream> resourceSupplier, String resourceName) {
try (InputStream inputStream = Objects.requireNonNull(resourceSupplier.apply(resourceName));
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
+ List<String> specs = new ArrayList<>(10); // re-use for each line
while ((line = reader.readLine()) != null) {
- int commentPos = line.indexOf('#');
- if (commentPos >= 0) {
- line = line.substring(0, commentPos);
- }
- line = line.trim();
- if (line.isEmpty()) {
- continue;
- }
- List<String> specs = Arrays.asList(SPLIT_PATTERN.split(line));
- if (!allowOverwrite) {
- // Pretend that the mimeType and each file extension listed in the line
- // carries a "?" prefix, which means that it can add new mappings but
- // not modify existing mappings (putIfAbsent() semantics).
- specs = ensurePrefix("?", specs);
- }
+ specs.clear();
+ // Lines are of the form "mimeSpec extSpec extSpec[...]" with a single space
+ // separating them and no leading/trailing spaces and no empty lines.
+ int startIdx = 0;
+ do {
+ int endIdx = line.indexOf(' ', startIdx);
+ if (endIdx < 0) {
+ endIdx = line.length();
+ }
+ String spec = line.substring(startIdx, endIdx);
+ if (spec.isEmpty()) {
+ throw new IllegalArgumentException("Malformed line: " + line);
+ }
+ specs.add(spec);
+ startIdx = endIdx + 1; // skip over the space
+ } while (startIdx < line.length());
builder.put(specs.get(0), specs.subList(1, specs.size()));
}
} catch (IOException | RuntimeException e) {
@@ -97,15 +103,4 @@ public class DefaultMimeMapFactory {
}
}
- private static List<String> ensurePrefix(String prefix, List<String> strings) {
- List<String> result = new ArrayList<>(strings.size());
- for (String s : strings) {
- if (!s.startsWith(prefix)) {
- s = prefix + s;
- }
- result.add(s);
- }
- return result;
- }
-
}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
index 91b292666756..66be25b53a62 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/StreamUtils.java
@@ -18,9 +18,13 @@ package com.android.server.backup.encryption;
import java.io.Closeable;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
/** Utility methods for dealing with Streams */
public class StreamUtils {
+ private static final int MAX_COPY_BUFFER_SIZE = 1024; // 1k copy buffer size.
+
/**
* Close a Closeable and silently ignore any IOExceptions.
*
@@ -33,4 +37,28 @@ public class StreamUtils {
// Silently ignore
}
}
+
+ /**
+ * Copy data from an InputStream to an OutputStream upto a given number of bytes.
+ *
+ * @param in The source InputStream
+ * @param out The destination OutputStream
+ * @param limit The maximum number of bytes to copy
+ * @throws IOException Thrown if there is a problem performing the copy.
+ */
+ public static void copyStream(InputStream in, OutputStream out, int limit) throws IOException {
+ int bufferSize = Math.min(MAX_COPY_BUFFER_SIZE, limit);
+ byte[] buffer = new byte[bufferSize];
+
+ int copied = 0;
+ while (copied < limit) {
+ int maxReadSize = Math.min(bufferSize, limit - copied);
+ int read = in.read(buffer, 0, maxReadSize);
+ if (read < 0) {
+ return; // Reached the stream end before the limit
+ }
+ out.write(buffer, 0, read);
+ copied += read;
+ }
+ }
}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
new file mode 100644
index 000000000000..0baec8b0a450
--- /dev/null
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.tasks;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupTransport;
+import android.content.Context;
+import android.util.Slog;
+
+import com.android.server.backup.encryption.FullBackupDataProcessor;
+import com.android.server.backup.encryption.StreamUtils;
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.security.SecureRandom;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+/**
+ * Accepts backup data from a {@link InputStream} and passes it to the encrypted full data backup
+ * path.
+ */
+public class EncryptedFullBackupDataProcessor implements FullBackupDataProcessor {
+
+ private static final String TAG = "EncryptedFullBackupDP";
+
+ private final Context mContext;
+ private final ExecutorService mExecutorService;
+ private final CryptoBackupServer mCryptoBackupServer;
+ private final SecureRandom mSecureRandom;
+ private final RecoverableKeyStoreSecondaryKey mSecondaryKey;
+ private final String mPackageName;
+
+ @Nullable private InputStream mInputStream;
+ @Nullable private PipedOutputStream mOutputStream;
+ @Nullable private EncryptedFullBackupTask mBackupTask;
+ @Nullable private Future<Void> mBackupTaskFuture;
+ @Nullable private FullBackupCallbacks mFullBackupCallbacks;
+
+ public EncryptedFullBackupDataProcessor(
+ Context context,
+ ExecutorService executorService,
+ CryptoBackupServer cryptoBackupServer,
+ SecureRandom secureRandom,
+ RecoverableKeyStoreSecondaryKey secondaryKey,
+ String packageName) {
+ mContext = checkNotNull(context);
+ mExecutorService = checkNotNull(executorService);
+ mCryptoBackupServer = checkNotNull(cryptoBackupServer);
+ mSecureRandom = checkNotNull(secureRandom);
+ mSecondaryKey = checkNotNull(secondaryKey);
+ mPackageName = checkNotNull(packageName);
+ }
+
+ @Override
+ public boolean initiate(InputStream inputStream) throws IOException {
+ checkState(mBackupTask == null, "initiate() twice");
+
+ this.mInputStream = inputStream;
+ mOutputStream = new PipedOutputStream();
+
+ mBackupTask =
+ EncryptedFullBackupTask.newInstance(
+ mContext,
+ mCryptoBackupServer,
+ mSecureRandom,
+ mSecondaryKey,
+ mPackageName,
+ new PipedInputStream(mOutputStream));
+
+ return true;
+ }
+
+ @Override
+ public void start() {
+ checkState(mBackupTask != null, "start() before initiate()");
+ mBackupTaskFuture = mExecutorService.submit(mBackupTask);
+ }
+
+ @Override
+ public int pushData(int numBytes) {
+ checkState(
+ mBackupTaskFuture != null && mInputStream != null && mOutputStream != null,
+ "pushData() before start()");
+
+ // If the upload has failed then stop without pushing any more bytes.
+ if (mBackupTaskFuture.isDone()) {
+ Optional<Exception> exception = getTaskException();
+ Slog.e(TAG, "Encrypted upload failed", exception.orElse(null));
+ if (exception.isPresent()) {
+ reportNetworkFailureIfNecessary(exception.get());
+
+ if (exception.get().getCause() instanceof SizeQuotaExceededException) {
+ return BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
+ }
+ }
+
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
+ try {
+ StreamUtils.copyStream(mInputStream, mOutputStream, numBytes);
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when processing backup", e);
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
+ return BackupTransport.TRANSPORT_OK;
+ }
+
+ @Override
+ public void cancel() {
+ checkState(mBackupTaskFuture != null && mBackupTask != null, "cancel() before start()");
+ mBackupTask.cancel();
+ closeStreams();
+ }
+
+ @Override
+ public int finish() {
+ checkState(mBackupTaskFuture != null, "finish() before start()");
+
+ // getTaskException() waits for the task to finish. We must close the streams first, which
+ // causes the task to finish, otherwise it will block forever.
+ closeStreams();
+ Optional<Exception> exception = getTaskException();
+
+ if (exception.isPresent()) {
+ Slog.e(TAG, "Exception during encrypted full backup", exception.get());
+ reportNetworkFailureIfNecessary(exception.get());
+
+ if (exception.get().getCause() instanceof SizeQuotaExceededException) {
+ return BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
+ }
+ return BackupTransport.TRANSPORT_ERROR;
+
+ } else {
+ if (mFullBackupCallbacks != null) {
+ mFullBackupCallbacks.onSuccess();
+ }
+
+ return BackupTransport.TRANSPORT_OK;
+ }
+ }
+
+ private void closeStreams() {
+ StreamUtils.closeQuietly(mInputStream);
+ StreamUtils.closeQuietly(mOutputStream);
+ }
+
+ @Override
+ public void handleCheckSizeRejectionZeroBytes() {
+ cancel();
+ }
+
+ @Override
+ public void handleCheckSizeRejectionQuotaExceeded() {
+ cancel();
+ }
+
+ @Override
+ public void handleSendBytesQuotaExceeded() {
+ cancel();
+ }
+
+ @Override
+ public void attachCallbacks(FullBackupCallbacks fullBackupCallbacks) {
+ this.mFullBackupCallbacks = fullBackupCallbacks;
+ }
+
+ private void reportNetworkFailureIfNecessary(Exception exception) {
+ if (!(exception.getCause() instanceof SizeQuotaExceededException)
+ && mFullBackupCallbacks != null) {
+ mFullBackupCallbacks.onTransferFailed();
+ }
+ }
+
+ private Optional<Exception> getTaskException() {
+ if (mBackupTaskFuture != null) {
+ try {
+ mBackupTaskFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ return Optional.of(e);
+ }
+ }
+ return Optional.empty();
+ }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java
new file mode 100644
index 000000000000..a95e87e3a8b7
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/StreamUtilsTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+@RunWith(RobolectricTestRunner.class)
+public class StreamUtilsTest {
+ private static final int SOURCE_DATA_SIZE = 64;
+
+ private byte[] mSourceData;
+
+ private InputStream mSource;
+ private ByteArrayOutputStream mDestination;
+
+ @Before
+ public void setUp() {
+ mSourceData = new byte[SOURCE_DATA_SIZE];
+ for (byte i = 0; i < SOURCE_DATA_SIZE; i++) {
+ mSourceData[i] = i;
+ }
+ mSource = new ByteArrayInputStream(mSourceData);
+ mDestination = new ByteArrayOutputStream();
+ }
+
+ @Test
+ public void copyStream_copiesAllBytesIfAsked() throws IOException {
+ StreamUtils.copyStream(mSource, mDestination, mSourceData.length);
+ assertOutputHasBytes(mSourceData.length);
+ }
+
+ @Test
+ public void copyStream_stopsShortIfAsked() throws IOException {
+ StreamUtils.copyStream(mSource, mDestination, mSourceData.length - 10);
+ assertOutputHasBytes(mSourceData.length - 10);
+ }
+
+ @Test
+ public void copyStream_stopsShortIfAskedToCopyMoreThanAvailable() throws IOException {
+ StreamUtils.copyStream(mSource, mDestination, mSourceData.length + 10);
+ assertOutputHasBytes(mSourceData.length);
+ }
+
+ private void assertOutputHasBytes(int count) {
+ byte[] output = mDestination.toByteArray();
+ assertThat(output.length).isEqualTo(count);
+ for (int i = 0; i < count; i++) {
+ assertThat(output[i]).isEqualTo(mSourceData[i]);
+ }
+ }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java
new file mode 100644
index 000000000000..675d03fb9869
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessorTest.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.tasks;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.testng.Assert.assertThrows;
+
+import android.annotation.Nullable;
+import android.app.backup.BackupTransport;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.server.backup.encryption.FullBackupDataProcessor;
+import com.android.server.backup.encryption.chunking.ProtoStore;
+import com.android.server.backup.encryption.client.CryptoBackupServer;
+import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKey;
+import com.android.server.backup.encryption.keys.TertiaryKeyManager;
+import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;
+import com.android.server.backup.encryption.testing.QueuingNonAutomaticExecutorService;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.primitives.Bytes;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+
+import javax.crypto.spec.SecretKeySpec;
+
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+@Config(
+ shadows = {
+ EncryptedFullBackupDataProcessorTest.ShadowEncryptedFullBackupTask.class,
+ })
+public class EncryptedFullBackupDataProcessorTest {
+
+ private static final String KEY_GENERATOR_ALGORITHM = "AES";
+
+ private static final String TEST_PACKAGE = "com.example.app1";
+ private static final byte[] TEST_DATA_1 = {1, 2, 3, 4};
+ private static final byte[] TEST_DATA_2 = {5, 6, 7, 8};
+
+ private final RecoverableKeyStoreSecondaryKey mTestSecondaryKey =
+ new RecoverableKeyStoreSecondaryKey(
+ /*alias=*/ "test_key",
+ new SecretKeySpec(
+ new byte[] {
+ 1, 2, 3,
+ },
+ KEY_GENERATOR_ALGORITHM));
+
+ private QueuingNonAutomaticExecutorService mExecutorService;
+ private FullBackupDataProcessor mFullBackupDataProcessor;
+ @Mock private FullBackupDataProcessor.FullBackupCallbacks mFullBackupCallbacks;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mExecutorService = new QueuingNonAutomaticExecutorService();
+ mFullBackupDataProcessor =
+ new EncryptedFullBackupDataProcessor(
+ ApplicationProvider.getApplicationContext(),
+ mExecutorService,
+ mock(CryptoBackupServer.class),
+ new SecureRandom(),
+ mTestSecondaryKey,
+ TEST_PACKAGE);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowEncryptedFullBackupTask.reset();
+ }
+
+ @Test
+ public void initiate_callTwice_throws() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10]));
+
+ assertThrows(
+ IllegalStateException.class,
+ () -> mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10])));
+ }
+
+ @Test
+ public void pushData_writesDataToTask() throws Exception {
+ byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+ finishBackupTask();
+ mFullBackupDataProcessor.finish();
+
+ byte[] result = ByteStreams.toByteArray(ShadowEncryptedFullBackupTask.sInputStream);
+ assertThat(result).isEqualTo(Bytes.concat(TEST_DATA_1, TEST_DATA_2));
+ }
+
+ @Test
+ public void pushData_noError_returnsOk() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ int result = mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTask();
+ mFullBackupDataProcessor.finish();
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_OK);
+ }
+
+ @Test
+ public void pushData_ioExceptionOnCopy_returnsError() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+
+ // Close the stream so there's an IO error when the processor tries to write to it.
+ ShadowEncryptedFullBackupTask.sInputStream.close();
+ int result = mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+
+ finishBackupTask();
+ mFullBackupDataProcessor.finish();
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+ }
+
+ @Test
+ public void pushData_exceptionDuringUpload_returnsError() throws Exception {
+ byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new IOException("Test exception"));
+ int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+ }
+
+ @Test
+ public void pushData_quotaExceptionDuringUpload_doesNotLogAndReturnsQuotaExceeded()
+ throws Exception {
+ mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+ byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new SizeQuotaExceededException());
+ int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+
+ verify(mFullBackupCallbacks, never()).onSuccess();
+ verify(mFullBackupCallbacks, never())
+ .onTransferFailed(); // FullBackupSession will handle this.
+ }
+
+ @Test
+ public void pushData_unexpectedEncryptedBackup_logs() throws Exception {
+ byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new GeneralSecurityException());
+ int result = mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+ }
+
+ @Test
+ public void pushData_permanentExceptionDuringUpload_callsErrorCallback() throws Exception {
+ mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+ byte[] inputData = Bytes.concat(TEST_DATA_1, TEST_DATA_2);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(inputData));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new IOException());
+ mFullBackupDataProcessor.pushData(TEST_DATA_2.length);
+
+ verify(mFullBackupCallbacks, never()).onSuccess();
+ verify(mFullBackupCallbacks).onTransferFailed();
+ }
+
+ @Test
+ public void pushData_beforeInitiate_throws() {
+ assertThrows(
+ IllegalStateException.class,
+ () -> mFullBackupDataProcessor.pushData(/*numBytes=*/ 10));
+ }
+
+ @Test
+ public void cancel_cancelsTask() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ mFullBackupDataProcessor.cancel();
+
+ assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+ }
+
+ @Test
+ public void cancel_beforeInitiate_throws() {
+ assertThrows(IllegalStateException.class, () -> mFullBackupDataProcessor.cancel());
+ }
+
+ @Test
+ public void finish_noException_returnsTransportOk() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTask();
+ int result = mFullBackupDataProcessor.finish();
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_OK);
+ }
+
+ @Test
+ public void finish_exceptionDuringUpload_returnsTransportError() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new IOException("Test exception"));
+ int result = mFullBackupDataProcessor.finish();
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_ERROR);
+ }
+
+ @Test
+ public void finish_successfulBackup_callsSuccessCallback() throws Exception {
+ mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTask();
+ mFullBackupDataProcessor.finish();
+
+ verify(mFullBackupCallbacks).onSuccess();
+ verify(mFullBackupCallbacks, never()).onTransferFailed();
+ }
+
+ @Test
+ public void finish_backupFailedWithPermanentError_callsErrorCallback() throws Exception {
+ mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new IOException());
+ mFullBackupDataProcessor.finish();
+
+ verify(mFullBackupCallbacks, never()).onSuccess();
+ verify(mFullBackupCallbacks).onTransferFailed();
+ }
+
+ @Test
+ public void finish_backupFailedWithQuotaException_doesNotCallbackAndReturnsQuotaExceeded()
+ throws Exception {
+ mFullBackupDataProcessor.attachCallbacks(mFullBackupCallbacks);
+
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ finishBackupTaskWithException(new SizeQuotaExceededException());
+ int result = mFullBackupDataProcessor.finish();
+
+ assertThat(result).isEqualTo(BackupTransport.TRANSPORT_QUOTA_EXCEEDED);
+ verify(mFullBackupCallbacks, never()).onSuccess();
+ verify(mFullBackupCallbacks, never())
+ .onTransferFailed(); // FullBackupSession will handle this.
+ }
+
+ @Test
+ public void finish_beforeInitiate_throws() {
+ assertThrows(IllegalStateException.class, () -> mFullBackupDataProcessor.finish());
+ }
+
+ @Test
+ public void handleCheckSizeRejectionZeroBytes_cancelsTask() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(new byte[10]));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.handleCheckSizeRejectionZeroBytes();
+
+ assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+ }
+
+ @Test
+ public void handleCheckSizeRejectionQuotaExceeded_cancelsTask() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ mFullBackupDataProcessor.handleCheckSizeRejectionQuotaExceeded();
+
+ assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+ }
+
+ @Test
+ public void handleSendBytesQuotaExceeded_cancelsTask() throws Exception {
+ mFullBackupDataProcessor.initiate(new ByteArrayInputStream(TEST_DATA_1));
+ mFullBackupDataProcessor.start();
+ mFullBackupDataProcessor.pushData(TEST_DATA_1.length);
+ mFullBackupDataProcessor.handleSendBytesQuotaExceeded();
+
+ assertThat(ShadowEncryptedFullBackupTask.sCancelled).isTrue();
+ }
+
+ private void finishBackupTask() {
+ mExecutorService.runNext();
+ }
+
+ private void finishBackupTaskWithException(Exception exception) {
+ ShadowEncryptedFullBackupTask.sOnCallException = exception;
+ finishBackupTask();
+ }
+
+ @Implements(EncryptedFullBackupTask.class)
+ public static class ShadowEncryptedFullBackupTask {
+
+ private static InputStream sInputStream;
+ @Nullable private static Exception sOnCallException;
+ private static boolean sCancelled;
+
+ public void __constructor__(
+ ProtoStore<ChunksMetadataProto.ChunkListing> chunkListingStore,
+ TertiaryKeyManager tertiaryKeyManager,
+ EncryptedBackupTask task,
+ InputStream inputStream,
+ String packageName,
+ SecureRandom secureRandom) {
+ sInputStream = inputStream;
+ }
+
+ @Implementation
+ public Void call() throws Exception {
+ if (sOnCallException != null) {
+ throw sOnCallException;
+ }
+
+ return null;
+ }
+
+ @Implementation
+ public void cancel() {
+ sCancelled = true;
+ }
+
+ public static void reset() {
+ sOnCallException = null;
+ sCancelled = false;
+ }
+ }
+}
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java
new file mode 100644
index 000000000000..9d2272e29945
--- /dev/null
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/QueuingNonAutomaticExecutorService.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.testing;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * ExecutorService which needs to be stepped through the jobs in its' queue.
+ *
+ * <p>This is a deliberately simple implementation because it's only used in testing. The queued
+ * jobs are run on the main thread to eliminate any race condition bugs.
+ */
+public class QueuingNonAutomaticExecutorService extends AbstractExecutorService {
+
+ private List<Runnable> mWaitingJobs = new ArrayList<>();
+ private int mWaitingJobCount = 0;
+
+ @Override
+ public void shutdown() {
+ mWaitingJobCount = mWaitingJobs.size();
+ mWaitingJobs = null; // This will force an error if jobs are submitted after shutdown
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ List<Runnable> queuedJobs = mWaitingJobs;
+ shutdown();
+ return queuedJobs;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return mWaitingJobs == null;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return mWaitingJobs == null && mWaitingJobCount == 0;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ long expiry = System.currentTimeMillis() + unit.toMillis(timeout);
+ for (Runnable job : mWaitingJobs) {
+ if (System.currentTimeMillis() > expiry) {
+ return false;
+ }
+
+ job.run();
+ }
+ return true;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ mWaitingJobs.add(command);
+ }
+
+ public void runNext() {
+ if (mWaitingJobs.isEmpty()) {
+ throw new IllegalStateException("Attempted to run jobs on an empty paused executor");
+ }
+
+ mWaitingJobs.remove(0).run();
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index c205bb49228c..53a88a9a54e9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -20,6 +20,7 @@ import android.service.notification.StatusBarNotification;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -34,8 +35,8 @@ import javax.inject.Singleton;
public class CarNotificationEntryManager extends NotificationEntryManager {
@Inject
- public CarNotificationEntryManager(NotificationData notificationData) {
- super(notificationData);
+ public CarNotificationEntryManager(NotificationData notificationData, NotifLog notifLog) {
+ super(notificationData, notifLog);
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index cc6e84259893..681d8f543575 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -108,6 +108,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -296,7 +297,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
NotificationListener notificationListener,
ConfigurationController configurationController,
StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuild) {
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuild,
+ NotifLog notifLog) {
super(
lightBarController,
autoHideController,
@@ -350,7 +352,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
notificationListener,
configurationController,
statusBarWindowController,
- statusBarWindowViewControllerBuild);
+ statusBarWindowViewControllerBuild,
+ notifLog);
mNavigationBarController = navigationBarController;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index c05c4cdf72d7..de6a3a8840a4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Binder;
import android.os.Build;
@@ -49,7 +48,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
-import com.android.server.LocalServices;
import libcore.io.IoUtils;
@@ -1175,9 +1173,8 @@ final class SettingsState {
}
// If SetupWizard, done.
- PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- if (packageName.equals(packageManagerInternal.getSetupWizardPackageName())) {
+ String setupWizPackage = context.getPackageManager().getSetupWizardPackageName();
+ if (packageName.equals(setupWizPackage)) {
sSystemUids.put(uid, uid);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
index f9ffb804f9f3..5010f319f8b4 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleViewController.java
@@ -43,6 +43,7 @@ public class AssistHandleViewController implements NavigationBarTransitions.Dark
private Handler mHandler;
private CornerHandleView mAssistHintLeft;
private CornerHandleView mAssistHintRight;
+ private int mBottomOffset;
@VisibleForTesting
boolean mAssistHintVisible;
@@ -62,6 +63,23 @@ public class AssistHandleViewController implements NavigationBarTransitions.Dark
}
/**
+ * Set the bottom offset.
+ *
+ * @param bottomOffset the bottom offset to translate.
+ */
+ public void setBottomOffset(int bottomOffset) {
+ if (mBottomOffset != bottomOffset) {
+ mBottomOffset = bottomOffset;
+ if (mAssistHintVisible) {
+ // If assist handles are visible, hide them without animation and then make them
+ // show once again (with corrected bottom offset).
+ hideAssistHandles();
+ setAssistHintVisible(true);
+ }
+ }
+ }
+
+ /**
* Controls the visibility of the assist gesture handles.
*
* @param visible whether the handles should be shown
@@ -126,7 +144,8 @@ public class AssistHandleViewController implements NavigationBarTransitions.Dark
xDirection * translationStart * view.getWidth(),
xDirection * translationEnd * view.getWidth());
Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
- translationStart * view.getHeight(), translationEnd * view.getHeight());
+ translationStart * view.getHeight() + mBottomOffset,
+ translationEnd * view.getHeight() + mBottomOffset);
AnimatorSet set = new AnimatorSet();
set.play(scaleX).with(scaleY);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 824034507019..cc548d0c7f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -569,7 +569,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (mStackView != null) {
mStackView.updateDotVisibility(entry.key);
}
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleController.onNotificationRemoveRequested");
return true;
} else if (!userRemovedNotif && entry != null) {
// This wasn't a user removal so we should remove the bubble as well
@@ -609,7 +610,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mBubbleData.addSummaryToSuppress(summary.notification.getGroupKey(),
summary.key);
// Tell shade to update for the suppression
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleController.handleSummaryRemovalInterception");
}
return !isAutogroupSummary;
} else {
@@ -760,7 +762,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mStackView.setExpanded(true);
}
- mNotificationEntryManager.updateNotifications();
+ mNotificationEntryManager.updateNotifications(
+ "BubbleData.Listener.applyUpdate");
updateStack();
if (DEBUG_BUBBLE_CONTROLLER) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 6c0f90a65ae9..c4de2d3572bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -127,7 +127,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
} else {
mEntryManager.getNotificationData()
- .updateRanking(rankingMap);
+ .updateRanking(rankingMap, "onNotificationPosted");
}
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 4ba111436048..6ffea79c420a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -106,7 +106,7 @@ public class NotificationLockscreenUserManagerImpl implements
isCurrentProfile(getSendingUserId())) {
mUsersAllowingPrivateNotifications.clear();
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
}
}
};
@@ -124,7 +124,7 @@ public class NotificationLockscreenUserManagerImpl implements
updatePublicMode();
// The filtering needs to happen before the update call below in order to make sure
// the presenter has the updated notifications from the new user
- getEntryManager().getNotificationData().filterAndSort();
+ getEntryManager().getNotificationData().filterAndSort("user switched");
mPresenter.onUserSwitched(mCurrentUserId);
for (UserChangedListener listener : mListeners) {
@@ -205,7 +205,8 @@ public class NotificationLockscreenUserManagerImpl implements
mUsersAllowingNotifications.clear();
// ... and refresh all the notifications
updateLockscreenNotificationSetting();
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
+ + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
}
};
@@ -214,7 +215,8 @@ public class NotificationLockscreenUserManagerImpl implements
public void onChange(boolean selfChange) {
updateLockscreenNotificationSetting();
if (mDeviceProvisionedController.isDeviceProvisioned()) {
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
+ + " or ZEN_MODE change");
}
}
};
@@ -532,7 +534,7 @@ public class NotificationLockscreenUserManagerImpl implements
setLockscreenPublicMode(isProfilePublic, userId);
mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
}
- getEntryManager().updateNotifications();
+ getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index c50fb3d76b51..3616b541741c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -361,7 +361,7 @@ public class NotificationMediaManager implements Dumpable {
}
if (metaDataChanged) {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("NotificationMediaManager - metaDataChanged");
}
dispatchUpdateMediaMetaData(metaDataChanged, true /* allowEnterAnimation */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 148a1a87f305..01c79b3df064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -40,6 +40,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
@@ -92,6 +94,7 @@ public class NotificationEntryManager implements
private NotificationListenerService.RankingMap mLatestRankingMap;
@VisibleForTesting
protected NotificationData mNotificationData;
+ private NotifLog mNotifLog;
@VisibleForTesting
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
@@ -123,8 +126,9 @@ public class NotificationEntryManager implements
}
@Inject
- public NotificationEntryManager(NotificationData notificationData) {
+ public NotificationEntryManager(NotificationData notificationData, NotifLog notifLog) {
mNotificationData = notificationData;
+ mNotifLog = notifLog;
}
/** Adds a {@link NotificationEntryListener}. */
@@ -178,7 +182,7 @@ public class NotificationEntryManager implements
@Override
public void onReorderingAllowed() {
- updateNotifications();
+ updateNotifications("reordering is now allowed");
}
/**
@@ -203,15 +207,19 @@ public class NotificationEntryManager implements
return NotificationVisibility.obtain(key, rank, count, true, location);
}
- private void abortExistingInflation(String key) {
+ private void abortExistingInflation(String key, String reason) {
if (mPendingNotifications.containsKey(key)) {
NotificationEntry entry = mPendingNotifications.get(key);
entry.abortTask();
mPendingNotifications.remove(key);
+ mNotifLog.log(NotifEvent.INFLATION_ABORTED, entry.sbn(), null,
+ "PendingNotification aborted. " + reason);
}
NotificationEntry addedEntry = mNotificationData.get(key);
if (addedEntry != null) {
addedEntry.abortTask();
+ mNotifLog.log(NotifEvent.INFLATION_ABORTED, addedEntry.sbn(),
+ null, reason);
}
}
@@ -247,7 +255,7 @@ public class NotificationEntryManager implements
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onBeforeNotificationAdded(entry);
}
- updateNotifications();
+ updateNotifications("onAsyncInflationFinished");
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationAdded(entry);
}
@@ -276,7 +284,8 @@ public class NotificationEntryManager implements
if (mRemoveInterceptor != null
&& mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) {
- // Remove intercepted; skip
+ // Remove intercepted; log and skip
+ mNotifLog.log(NotifEvent.REMOVE_INTERCEPTED);
return;
}
@@ -291,13 +300,17 @@ public class NotificationEntryManager implements
if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) {
extendLifetime(pendingEntry, extender);
lifetimeExtended = true;
+ mNotifLog.log(
+ NotifEvent.LIFETIME_EXTENDED,
+ pendingEntry.sbn(),
+ "pendingEntry extendedBy=" + extender.toString());
}
}
}
}
if (!lifetimeExtended) {
- abortExistingInflation(key);
+ abortExistingInflation(key, "removeNotification");
}
if (entry != null) {
@@ -310,6 +323,10 @@ public class NotificationEntryManager implements
mLatestRankingMap = ranking;
extendLifetime(entry, extender);
lifetimeExtended = true;
+ mNotifLog.log(
+ NotifEvent.LIFETIME_EXTENDED,
+ entry.sbn(),
+ "entry extendedBy=" + extender.toString());
break;
}
}
@@ -329,10 +346,12 @@ public class NotificationEntryManager implements
handleGroupSummaryRemoved(key);
mNotificationData.remove(key, ranking);
- updateNotifications();
+ updateNotifications("removeNotificationInternal");
Dependency.get(LeakDetector.class).trackGarbage(entry);
removedByUser |= entryDismissed;
+ mNotifLog.log(NotifEvent.NOTIF_REMOVED, entry.sbn(),
+ "removedByUser=" + removedByUser);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryRemoved(entry, visibility, removedByUser);
}
@@ -389,7 +408,7 @@ public class NotificationEntryManager implements
Log.d(TAG, "addNotification key=" + key);
}
- mNotificationData.updateRanking(rankingMap);
+ mNotificationData.updateRanking(rankingMap, "addNotificationInternal");
Ranking ranking = new Ranking();
rankingMap.getRanking(key, ranking);
@@ -400,9 +419,9 @@ public class NotificationEntryManager implements
requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
REASON_CANCEL));
- abortExistingInflation(key);
-
+ abortExistingInflation(key, "addNotification");
mPendingNotifications.put(key, entry);
+ mNotifLog.log(NotifEvent.NOTIF_ADDED, entry.sbn());
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPendingEntryAdded(entry);
}
@@ -423,7 +442,7 @@ public class NotificationEntryManager implements
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final String key = notification.getKey();
- abortExistingInflation(key);
+ abortExistingInflation(key, "updateNotification");
NotificationEntry entry = mNotificationData.get(key);
if (entry == null) {
return;
@@ -433,15 +452,15 @@ public class NotificationEntryManager implements
// to keep its lifetime extended.
cancelLifetimeExtension(entry);
- mNotificationData.update(entry, ranking, notification);
-
+ mNotificationData.update(entry, ranking, notification, "updateNotificationInternal");
+ mNotifLog.log(NotifEvent.NOTIF_UPDATED, entry.sbn(), entry.ranking());
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onPreEntryUpdated(entry);
}
requireBinder().inflateViews(entry, () -> performRemoveNotification(notification,
REASON_CANCEL));
- updateNotifications();
+ updateNotifications("updateNotificationInternal");
if (DEBUG) {
// Is this for you?
@@ -465,8 +484,12 @@ public class NotificationEntryManager implements
}
}
- public void updateNotifications() {
- mNotificationData.filterAndSort();
+ /**
+ * Update the notifications
+ * @param reason why the notifications are updating
+ */
+ public void updateNotifications(String reason) {
+ mNotificationData.filterAndSort(reason);
if (mPresenter != null) {
mPresenter.updateNotificationViews();
}
@@ -489,7 +512,7 @@ public class NotificationEntryManager implements
}
// Populate notification entries from the new rankings.
- mNotificationData.updateRanking(rankingMap);
+ mNotificationData.updateRanking(rankingMap, "updateNotificationRanking");
updateRankingOfPendingNotifications(rankingMap);
// By comparing the old and new UI adjustments, reinflate the view accordingly.
@@ -501,7 +524,7 @@ public class NotificationEntryManager implements
NotificationUiAdjustment.extractFromNotificationEntry(entry));
}
- updateNotifications();
+ updateNotifications("updateNotificationRanking");
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationRankingUpdated(rankingMap);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
index 769cbb7b984c..970cbf9aa1e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -81,7 +81,7 @@ public class NotificationListController {
new DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("device provisioned changed");
}
};
@@ -106,7 +106,7 @@ public class NotificationListController {
if (foregroundKey != null) {
mEntryManager
.getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("app opp changed pkg=" + pkg);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index cf0fbbb5d9c1..a98fa664a357 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -35,6 +35,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -73,10 +75,13 @@ public class NotificationData {
private RankingMap mRankingMap;
private final Ranking mTmpRanking = new Ranking();
private final boolean mUsePeopleFiltering;
+ private final NotifLog mNotifLog;
@Inject
- public NotificationData(NotificationSectionsFeatureManager sectionsFeatureManager) {
+ public NotificationData(NotificationSectionsFeatureManager sectionsFeatureManager,
+ NotifLog notifLog) {
mUsePeopleFiltering = sectionsFeatureManager.isFilteringEnabled();
+ mNotifLog = notifLog;
}
public void setHeadsUpManager(HeadsUpManager headsUpManager) {
@@ -179,7 +184,7 @@ public class NotificationData {
}
mGroupManager.onEntryAdded(entry);
- updateRankingAndSort(mRankingMap);
+ updateRankingAndSort(mRankingMap, "addEntry=" + entry.sbn());
}
public NotificationEntry remove(String key, RankingMap ranking) {
@@ -189,7 +194,7 @@ public class NotificationData {
}
if (removed == null) return null;
mGroupManager.onEntryRemoved(removed);
- updateRankingAndSort(ranking);
+ updateRankingAndSort(ranking, "removeEntry=" + removed.sbn());
return removed;
}
@@ -197,15 +202,19 @@ public class NotificationData {
public void update(
NotificationEntry entry,
RankingMap ranking,
- StatusBarNotification notification) {
- updateRanking(ranking);
+ StatusBarNotification notification,
+ String reason) {
+ updateRanking(ranking, reason);
final StatusBarNotification oldNotification = entry.notification;
entry.setNotification(notification);
mGroupManager.onEntryUpdated(entry, oldNotification);
}
- public void updateRanking(RankingMap ranking) {
- updateRankingAndSort(ranking);
+ /**
+ * Update ranking and trigger a re-sort
+ */
+ public void updateRanking(RankingMap ranking, String reason) {
+ updateRankingAndSort(ranking, reason);
}
public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
@@ -352,7 +361,7 @@ public class NotificationData {
return false;
}
- private void updateRankingAndSort(RankingMap rankingMap) {
+ private void updateRankingAndSort(RankingMap rankingMap, String reason) {
if (rankingMap != null) {
mRankingMap = rankingMap;
synchronized (mEntries) {
@@ -375,7 +384,7 @@ public class NotificationData {
}
}
}
- filterAndSort();
+ filterAndSort(reason);
}
/**
@@ -393,7 +402,11 @@ public class NotificationData {
// TODO: This should not be public. Instead the Environment should notify this class when
// anything changed, and this class should call back the UI so it updates itself.
- public void filterAndSort() {
+ /**
+ * Filters and sorts the list of notification entries
+ */
+ public void filterAndSort(String reason) {
+ mNotifLog.log(NotifEvent.FILTER_AND_SORT, reason);
mSortedAndFiltered.clear();
synchronized (mEntries) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 60cf995ad8d1..e5571b64cc9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -41,6 +41,8 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotifEvent;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -72,6 +74,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private final boolean mAllowLongPress;
private final KeyguardBypassController mKeyguardBypassController;
private final StatusBarStateController mStatusBarStateController;
+ private final NotifLog mNotifLog;
private NotificationRemoteInputManager mRemoteInputManager;
private NotificationPresenter mPresenter;
@@ -85,12 +88,14 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
public NotificationRowBinderImpl(Context context, boolean allowLongPress,
KeyguardBypassController keyguardBypassController,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController,
+ NotifLog notifLog) {
mContext = context;
mMessagingUtil = new NotificationMessagingUtil(context);
mAllowLongPress = allowLongPress;
mKeyguardBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
+ mNotifLog = notifLog;
}
private NotificationRemoteInputManager getRemoteInputManager() {
@@ -143,6 +148,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
row -> {
bindRow(entry, pmUser, sbn, row, onDismissRunnable);
updateNotification(entry, pmUser, sbn, row);
+ mNotifLog.log(NotifEvent.INFLATED, sbn);
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index 2396d28bd46d..7703cbd94e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -30,9 +30,9 @@ import java.lang.annotation.RetentionPolicy;
* and triaging purposes.
*/
public class NotifEvent extends RichEvent {
- public static final int TOTAL_EVENT_TYPES = 8;
- private StatusBarNotification mSbn;
- private Ranking mRanking;
+ public static final int TOTAL_EVENT_TYPES = 11;
+ private final StatusBarNotification mSbn;
+ private final Ranking mRanking;
/**
* Creates a NotifEvent with an event type that matches with an index in the array
@@ -44,9 +44,20 @@ public class NotifEvent extends RichEvent {
public NotifEvent(int logLevel, int type, String reason, StatusBarNotification sbn,
Ranking ranking) {
super(logLevel, type, reason);
- mSbn = sbn.clone();
- mRanking = new Ranking();
- mRanking.populate(ranking);
+
+ if (sbn != null) {
+ mSbn = sbn.cloneLight();
+ } else {
+ mSbn = null;
+ }
+
+ if (ranking != null) {
+ mRanking = new Ranking();
+ mRanking.populate(ranking);
+ } else {
+ mRanking = null;
+ }
+
mMessage += getExtraInfo();
}
@@ -76,11 +87,14 @@ public class NotifEvent extends RichEvent {
"NotifAdded",
"NotifRemoved",
"NotifUpdated",
- "HeadsUpStarted",
- "HeadsUpEnded",
"Filter",
"Sort",
+ "FilterAndSort",
"NotifVisibilityChanged",
+ "LifetimeExtended",
+ "RemoveIntercepted",
+ "InflationAborted",
+ "Inflated"
};
if (events.length != TOTAL_EVENT_TYPES) {
@@ -135,8 +149,19 @@ public class NotifEvent extends RichEvent {
}
}
- @IntDef({NOTIF_ADDED, NOTIF_REMOVED, NOTIF_UPDATED, HEADS_UP_STARTED, HEADS_UP_ENDED, FILTER,
- SORT, NOTIF_VISIBILITY_CHANGED})
+ @IntDef({NOTIF_ADDED,
+ NOTIF_REMOVED,
+ NOTIF_UPDATED,
+ FILTER,
+ SORT,
+ FILTER_AND_SORT,
+ NOTIF_VISIBILITY_CHANGED,
+ LIFETIME_EXTENDED,
+ REMOVE_INTERCEPTED,
+ INFLATION_ABORTED,
+ INFLATED
+ })
+
/**
* Types of NotifEvents
*/
@@ -145,9 +170,13 @@ public class NotifEvent extends RichEvent {
public static final int NOTIF_ADDED = 0;
public static final int NOTIF_REMOVED = 1;
public static final int NOTIF_UPDATED = 2;
- public static final int HEADS_UP_STARTED = 3;
- public static final int HEADS_UP_ENDED = 4;
- public static final int FILTER = 5;
- public static final int SORT = 6;
- public static final int NOTIF_VISIBILITY_CHANGED = 7;
+ public static final int FILTER = 3;
+ public static final int SORT = 4;
+ public static final int FILTER_AND_SORT = 5;
+ public static final int NOTIF_VISIBILITY_CHANGED = 6;
+ public static final int LIFETIME_EXTENDED = 7;
+ // unable to remove notif - removal intercepted by {@link NotificationRemoveInterceptor}
+ public static final int REMOVE_INTERCEPTED = 8;
+ public static final int INFLATION_ABORTED = 9;
+ public static final int INFLATED = 10;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
index d42cd82f9784..8466d2e83002 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifLog.java
@@ -82,6 +82,14 @@ public class NotifLog extends SysuiLog {
}
/**
+ * Logs a {@link NotifEvent} with a notification
+ * @return true if successfully logged, else false
+ */
+ public boolean log(@NotifEvent.EventType int eventType, StatusBarNotification sbn, String msg) {
+ return log(eventType, sbn, null, msg);
+ }
+
+ /**
* Logs a {@link NotifEvent} with a ranking
* @return true if successfully logged, else false
*/
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 9f4b026b3d38..924a3470b832 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
@@ -1447,6 +1447,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
setDismissed(fromAccessibility);
if (mEntry.isClearable()) {
+ // TODO: beverlyt, log dismissal
// TODO: track dismiss sentiment
if (mOnDismissRunnable != null) {
mOnDismissRunnable.run();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 73093c6f471f..37f63c9779f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -139,7 +139,8 @@ public class NotificationBlockingHelperManager {
mBlockingHelperRow.setBlockingHelperShowing(false);
if (mBlockingHelperRow.isAttachedToWindow()) {
- Dependency.get(NotificationEntryManager.class).updateNotifications();
+ Dependency.get(NotificationEntryManager.class).updateNotifications(
+ "dismissCurrentBlockingHelper");
}
mBlockingHelperRow = null;
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index f5705c5f643b..7bbe8188b402 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -5333,7 +5333,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
requestChildrenUpdate();
onUpdateRowStates();
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("StatusBar state changed");
updateVisibility();
}
@@ -6492,12 +6492,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
- mStatusBar.requestNotificationUpdate();
+ mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
}
@Override
public void onGroupsChanged() {
- mStatusBar.requestNotificationUpdate();
+ mStatusBar.requestNotificationUpdate("onGroupsChanged");
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index a1a47e1305f5..2aae5b1b9139 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -67,6 +67,7 @@ import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
@@ -75,6 +76,7 @@ import com.android.systemui.recents.RecentsOnboarding;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -1198,6 +1200,19 @@ public class NavigationBarView extends FrameLayout implements
// we're passing the insets onto the gesture handler since the back arrow is only
// conditionally added and doesn't always get all the insets.
mEdgeBackGestureHandler.setInsets(leftInset, rightInset);
+
+ // this allows assist handle to be drawn outside its bound so that it can align screen
+ // bottom by translating its y position.
+ final boolean shouldClip =
+ !isGesturalMode(mNavBarMode) || insets.getSystemWindowInsetBottom() == 0;
+ setClipChildren(shouldClip);
+ setClipToPadding(shouldClip);
+
+ AssistHandleViewController controller = Dependency.get(NavigationBarController.class)
+ .getAssistHandlerViewController();
+ if (controller != null) {
+ controller.setBottomOffset(insets.getSystemWindowInsetBottom());
+ }
return super.onApplyWindowInsets(insets);
}
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 6ce6dfaf3c20..2b80d2282661 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -210,6 +210,7 @@ import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -385,6 +386,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final BroadcastDispatcher mBroadcastDispatcher;
private final ConfigurationController mConfigurationController;
private final StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
+ private final NotifLog mNotifLog;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -585,7 +587,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onStrongAuthStateChanged(int userId) {
super.onStrongAuthStateChanged(userId);
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onStrongAuthStateChanged");
}
};
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
@@ -599,6 +601,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mPulsing;
private final BubbleController mBubbleController;
private final BubbleController.BubbleExpandListener mBubbleExpandListener;
+
private ActivityIntentHelper mActivityIntentHelper;
@Override
@@ -669,7 +672,8 @@ public class StatusBar extends SystemUI implements DemoMode,
NotificationListener notificationListener,
ConfigurationController configurationController,
StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder) {
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog) {
mLightBarController = lightBarController;
mAutoHideController = autoHideController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -723,10 +727,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mConfigurationController = configurationController;
mStatusBarWindowController = statusBarWindowController;
mStatusBarWindowViewControllerBuilder = statusBarWindowViewControllerBuilder;
+ mNotifLog = notifLog;
mBubbleExpandListener =
(isExpanding, key) -> {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onBubbleExpandChanged");
updateScrimController();
};
}
@@ -1160,7 +1165,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mContext,
mAllowNotificationLongPress,
mKeyguardBypassController,
- mStatusBarStateController);
+ mStatusBarStateController,
+ mNotifLog);
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
@@ -1443,8 +1449,12 @@ public class StatusBar extends SystemUI implements DemoMode,
return mZenController.areNotificationsHiddenInShade();
}
- public void requestNotificationUpdate() {
- mEntryManager.updateNotifications();
+ /**
+ * Request a notification update
+ * @param reason why we're requesting a notification update
+ */
+ public void requestNotificationUpdate(String reason) {
+ mEntryManager.updateNotifications(reason);
}
/**
@@ -1685,7 +1695,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onHeadsUpStateChanged");
if (isDozing() && isHeadsUp) {
entry.setPulseSuppressed(false);
mDozeServiceHost.fireNotificationPulse(entry);
@@ -3566,7 +3576,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
- mEntryManager.updateNotifications();
+ mEntryManager.updateNotifications("onDozingChanged");
updateDozingState();
updateScrimController();
updateReportRejectedTouchVisibility();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 2798c6b56771..5a2b5e38222a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -91,7 +92,6 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class BubbleControllerTest extends SysuiTestCase {
-
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
@@ -223,13 +223,13 @@ public class BubbleControllerTest extends SysuiTestCase {
mBubbleController.updateBubble(mRow.getEntry());
assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
assertTrue(mBubbleController.hasBubbles());
- verify(mNotificationEntryManager).updateNotifications();
+ verify(mNotificationEntryManager).updateNotifications(any());
verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
- verify(mNotificationEntryManager, times(2)).updateNotifications();
+ verify(mNotificationEntryManager, times(2)).updateNotifications(anyString());
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
}
@@ -257,16 +257,16 @@ public class BubbleControllerTest extends SysuiTestCase {
@Test
public void testDismissStack() {
mBubbleController.updateBubble(mRow.getEntry());
- verify(mNotificationEntryManager, times(1)).updateNotifications();
+ verify(mNotificationEntryManager, times(1)).updateNotifications(any());
assertNotNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
mBubbleController.updateBubble(mRow2.getEntry());
- verify(mNotificationEntryManager, times(2)).updateNotifications();
+ verify(mNotificationEntryManager, times(2)).updateNotifications(any());
assertNotNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
assertTrue(mBubbleController.hasBubbles());
mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
assertFalse(mStatusBarWindowController.getBubblesShowing());
- verify(mNotificationEntryManager, times(3)).updateNotifications();
+ verify(mNotificationEntryManager, times(3)).updateNotifications(any());
assertNull(mBubbleData.getBubbleWithKey(mRow.getEntry().key));
assertNull(mBubbleData.getBubbleWithKey(mRow2.getEntry().key));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
index 618272cbcab0..cfa4065aed62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
@@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -31,15 +32,10 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.util.SparseArray;
-import android.view.Display;
-import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -59,7 +55,6 @@ import org.junit.runner.RunWith;
public class NavigationBarControllerTest extends SysuiTestCase {
private NavigationBarController mNavigationBarController;
- private Display mDisplay;
private NavigationBarFragment mDefaultNavBar;
private NavigationBarFragment mSecondaryNavBar;
@@ -89,37 +84,28 @@ public class NavigationBarControllerTest extends SysuiTestCase {
@After
public void tearDown() {
mNavigationBarController = null;
- mDisplay = null;
mDefaultNavBar = null;
mSecondaryNavBar = null;
}
@Test
public void testCreateNavigationBarsIncludeDefaultTrue() {
- initializeDisplayManager();
doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
mNavigationBarController.createNavigationBars(true, null);
- verify(mNavigationBarController).createNavigationBar(any(Display.class), any());
+ verify(mNavigationBarController).createNavigationBar(
+ argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
}
@Test
public void testCreateNavigationBarsIncludeDefaultFalse() {
- initializeDisplayManager();
doNothing().when(mNavigationBarController).createNavigationBar(any(), any());
mNavigationBarController.createNavigationBars(false, null);
- verify(mNavigationBarController, never()).createNavigationBar(any(), any());
- }
-
- private void initializeDisplayManager() {
- DisplayManager displayManager = mock(DisplayManager.class);
- mDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
- Display[] displays = {mDisplay};
- when(displayManager.getDisplays()).thenReturn(displays);
- mContext.addMockSystemService(Context.DISPLAY_SERVICE, displayManager);
+ verify(mNavigationBarController, never()).createNavigationBar(
+ argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any());
}
// Tests if NPE occurs when call checkNavBarModes() with invalid display.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index a02764320b6c..0569c55981fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -25,6 +25,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -99,7 +100,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
@Test
public void testLockScreenShowNotificationsChangeUpdatesNotifications() {
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
- verify(mEntryManager, times(1)).updateNotifications();
+ verify(mEntryManager, times(1)).updateNotifications(anyString());
}
@Test
@@ -138,7 +139,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
public void testSettingsObserverUpdatesNotifications() {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
mLockscreenUserManager.getSettingsObserverForTest().onChange(false);
- verify(mEntryManager, times(1)).updateNotifications();
+ verify(mEntryManager, times(1)).updateNotifications(anyString());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 866ea5112794..e52a25806086 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -28,6 +28,7 @@ import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -80,6 +81,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationData.K
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -146,7 +148,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
private final CountDownLatch mCountDownLatch;
TestableNotificationEntryManager() {
- super(new NotificationData(mock(NotificationSectionsFeatureManager.class)));
+ super(new NotificationData(mock(NotificationSectionsFeatureManager.class),
+ mock(NotifLog.class)), mock(NotifLog.class));
mCountDownLatch = new CountDownLatch(1);
}
@@ -259,7 +262,9 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
NotificationRowBinderImpl notificationRowBinder =
new NotificationRowBinderImpl(mContext, true, /* allowLongPress */
- mock(KeyguardBypassController.class), mock(StatusBarStateController.class));
+ mock(KeyguardBypassController.class),
+ mock(StatusBarStateController.class),
+ mock(NotifLog.class));
notificationRowBinder.setUpWithPresenter(
mPresenter, mListContainer, mHeadsUpManager, mEntryManager, mBindCallback);
notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
@@ -350,7 +355,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
// Ensure that update callbacks happen in correct order
InOrder order = inOrder(mEntryListener, notifData, mPresenter, mEntryListener);
order.verify(mEntryListener).onPreEntryUpdated(mEntry);
- order.verify(notifData).filterAndSort();
+ order.verify(notifData).filterAndSort(anyString());
order.verify(mPresenter).updateNotificationViews();
order.verify(mEntryListener).onPostEntryUpdated(mEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
index 6d275419ee94..8207a041ef50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -21,6 +21,7 @@ import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -43,6 +44,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -76,7 +78,7 @@ public class NotificationListControllerTest extends SysuiTestCase {
// TODO: Remove this once EntryManager no longer needs to be mocked
private NotificationData mNotificationData =
new NotificationData(new NotificationSectionsFeatureManager(
- new DeviceConfigProxyFake(), mContext));
+ new DeviceConfigProxyFake(), mContext), mock(NotifLog.class));
private int mNextNotifId = 0;
@@ -113,7 +115,7 @@ public class NotificationListControllerTest extends SysuiTestCase {
@Test
public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
mProvisionedListener.onDeviceProvisionedChanged();
- verify(mEntryManager).updateNotifications();
+ verify(mEntryManager).updateNotifications(anyString());
}
@Test
@@ -133,8 +135,8 @@ public class NotificationListControllerTest extends SysuiTestCase {
// THEN the app op is added to the entry
assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
- // THEN updateNotifications() is called
- verify(mEntryManager, times(1)).updateNotifications();
+ // THEN updateNotifications(TEST) is called
+ verify(mEntryManager, times(1)).updateNotifications(anyString());
}
@Test
@@ -146,8 +148,8 @@ public class NotificationListControllerTest extends SysuiTestCase {
// WHEN An unrelated notification gets a new app op
mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
- // THEN We never call updateNotifications()
- verify(mEntryManager, never()).updateNotifications();
+ // THEN We never call updateNotifications(TEST)
+ verify(mEntryManager, never()).updateNotifications(anyString());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 5fbacb1d7adf..59c76a8cbb77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -79,6 +79,7 @@ import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -141,7 +142,7 @@ public class NotificationDataTest extends SysuiTestCase {
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mNotificationData = new TestableNotificationData(
mock(NotificationSectionsFeatureManager.class));
- mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
+ mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class), "");
mRow = new NotificationTestHelper(getContext()).createRow();
Dependency.get(InitController.class).executePostInitTasks();
}
@@ -633,7 +634,7 @@ public class NotificationDataTest extends SysuiTestCase {
public static class TestableNotificationData extends NotificationData {
public TestableNotificationData(NotificationSectionsFeatureManager sectionsFeatureManager) {
- super(sectionsFeatureManager);
+ super(sectionsFeatureManager, mock(NotifLog.class));
}
public static final String OVERRIDE_RANK = "r";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
index 6d6439532912..cc89504cb54d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -62,7 +63,6 @@ import org.mockito.MockitoAnnotations;
@org.junit.runner.RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
-
private NotificationBlockingHelperManager mBlockingHelperManager;
private NotificationTestHelper mHelper;
@@ -112,7 +112,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
- verify(mEntryManager, times(0)).updateNotifications();
+ verify(mEntryManager, times(0)).updateNotifications(anyString());
}
@Test
@@ -125,7 +125,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
- verify(mEntryManager).updateNotifications();
+ verify(mEntryManager).updateNotifications(anyString());
}
@Test
@@ -267,7 +267,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
- verify(mEntryManager).updateNotifications();
+ verify(mEntryManager).updateNotifications(anyString());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 98485b311d17..95e9e67cb830 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -56,6 +56,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -232,7 +233,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mock(ShadeController.class),
mock(NotificationLockscreenUserManager.class),
new NotificationEntryManager(new NotificationData(mock(
- NotificationSectionsFeatureManager.class))),
+ NotificationSectionsFeatureManager.class), mock(NotifLog.class)),
+ mock(NotifLog.class)),
mock(DozeLog.class));
mNotificationStackScroller = mNotificationStackScrollLayout;
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 914717c0266d..12e9be15354f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -117,6 +117,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -218,6 +219,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private StatusBarWindowViewController.Builder mStatusBarWindowViewControllerBuilder;
@Mock private StatusBarWindowViewController mStatusBarWindowViewController;
+ @Mock private NotifLog mNotifLog;
@Before
public void setup() throws Exception {
@@ -339,7 +341,8 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationListener,
configurationController,
mStatusBarWindowController,
- mStatusBarWindowViewControllerBuilder);
+ mStatusBarWindowViewControllerBuilder,
+ mNotifLog);
// TODO: we should be able to call mStatusBar.start() and have all the below values
// initialized automatically.
mStatusBar.mContext = mContext;
@@ -873,7 +876,7 @@ public class StatusBarTest extends SysuiTestCase {
public static class TestableNotificationEntryManager extends NotificationEntryManager {
public TestableNotificationEntryManager(NotificationData notificationData) {
- super(notificationData);
+ super(notificationData, mock(NotifLog.class));
}
public void setUpForTest(NotificationPresenter presenter,
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 3eef92fc0aa7..1d666adff561 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -33,6 +33,8 @@ import android.os.PersistableBundle;
import android.util.ArraySet;
import android.util.SparseArray;
+import com.android.server.pm.PackageList;
+
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 35a06a977a58..09f62ff3fc56 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3064,11 +3064,6 @@ public class LocationManagerService extends ILocationManager.Stub {
try {
LocationProvider oldProvider = getLocationProviderLocked(name);
if (oldProvider != null) {
- if (oldProvider.isMock()) {
- throw new IllegalArgumentException(
- "Provider \"" + name + "\" already exists");
- }
-
removeProviderLocked(oldProvider);
}
@@ -3093,7 +3088,7 @@ public class LocationManagerService extends ILocationManager.Stub {
try {
LocationProvider testProvider = getLocationProviderLocked(name);
if (testProvider == null || !testProvider.isMock()) {
- throw new IllegalArgumentException("Provider \"" + name + "\" unknown");
+ return;
}
removeProviderLocked(testProvider);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7cbd1fcebb94..4bca7a126418 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5015,7 +5015,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (preBindAgent != null) {
thread.attachAgent(preBindAgent);
}
-
+ if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+ thread.attachStartupAgents(app.info.dataDir);
+ }
// Figure out whether the app needs to run in autofill compat mode.
AutofillOptions autofillOptions = null;
@@ -18353,7 +18355,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public int getCurrentUserId() {
- return mUserController.getCurrentUserIdLU();
+ return mUserController.getCurrentUserId();
}
@Override
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 798185ad88f7..6c4cc2d43866 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -65,7 +65,6 @@ import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
-import android.media.AudioAttributes;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@@ -109,6 +108,7 @@ import com.android.internal.app.IAppOpsNotedCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
@@ -257,6 +257,9 @@ public class AppOpsService extends IAppOpsService.Stub {
@GuardedBy("this")
private CheckOpsDelegate mCheckOpsDelegate;
+ @GuardedBy("this")
+ private SparseArray<List<Integer>> mSwitchOpToOps;
+
/**
* All times are in milliseconds. These constants are kept synchronized with the system
* global Settings. Any access to this class or its fields should be done while
@@ -1291,6 +1294,8 @@ public class AppOpsService extends IAppOpsService.Stub {
verifyIncomingOp(code);
code = AppOpsManager.opToSwitch(code);
+ updatePermissionRevokedCompat(uid, code, mode);
+
synchronized (this) {
final int defaultMode = AppOpsManager.opToDefaultMode(code);
@@ -1392,6 +1397,86 @@ public class AppOpsService extends IAppOpsService.Stub {
notifyOpChangedSync(code, uid, null, mode);
}
+ private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) {
+ PackageManager packageManager = mContext.getPackageManager();
+ String[] packageNames = packageManager.getPackagesForUid(uid);
+ if (ArrayUtils.isEmpty(packageNames)) {
+ return;
+ }
+ String packageName = packageNames[0];
+
+ List<Integer> ops = getSwitchOpToOps().get(switchCode);
+ int opsSize = CollectionUtils.size(ops);
+ for (int i = 0; i < opsSize; i++) {
+ int code = ops.get(i);
+
+ String permissionName = AppOpsManager.opToPermission(code);
+ if (permissionName == null) {
+ continue;
+ }
+
+ PermissionInfo permissionInfo;
+ try {
+ permissionInfo = packageManager.getPermissionInfo(permissionName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ continue;
+ }
+
+ if (!permissionInfo.isRuntime()) {
+ continue;
+ }
+
+ UserHandle user = UserHandle.getUserHandleForUid(uid);
+ boolean isRevokedCompat;
+ if (permissionInfo.backgroundPermission != null) {
+ boolean isBackgroundRevokedCompat = mode != AppOpsManager.MODE_ALLOWED;
+ long identity = Binder.clearCallingIdentity();
+ try {
+ packageManager.updatePermissionFlags(permissionInfo.backgroundPermission,
+ packageName, PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
+ isBackgroundRevokedCompat
+ ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED
+ && mode != AppOpsManager.MODE_FOREGROUND;
+ } else {
+ isRevokedCompat = mode != AppOpsManager.MODE_ALLOWED;
+ }
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ packageManager.updatePermissionFlags(permissionName, packageName,
+ PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, isRevokedCompat
+ ? PackageManager.FLAG_PERMISSION_REVOKED_COMPAT : 0, user);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @NonNull
+ private SparseArray<List<Integer>> getSwitchOpToOps() {
+ synchronized (this) {
+ if (mSwitchOpToOps == null) {
+ mSwitchOpToOps = new SparseArray<>();
+ for (int op = 0; op < _NUM_OP; op++) {
+ int switchOp = AppOpsManager.opToSwitch(op);
+ List<Integer> ops = mSwitchOpToOps.get(switchOp);
+ if (ops == null) {
+ ops = new ArrayList<>();
+ mSwitchOpToOps.put(switchOp, ops);
+ }
+ ops.add(op);
+ }
+ }
+ return mSwitchOpToOps;
+ }
+ }
+
private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
final StorageManagerInternal storageManagerInternal =
LocalServices.getService(StorageManagerInternal.class);
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index c46fc20b3cc8..29026e8affcf 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -114,6 +114,8 @@ final class ColorFade {
private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
+ private final Transaction mTransaction = new Transaction();
+
/**
* Animates an color fade warming up.
*/
@@ -659,14 +661,10 @@ final class ColorFade {
private boolean showSurface(float alpha) {
if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
- SurfaceControl.openTransaction();
- try {
- mSurfaceControl.setLayer(COLOR_FADE_LAYER);
- mSurfaceControl.setAlpha(alpha);
- mSurfaceControl.show();
- } finally {
- SurfaceControl.closeTransaction();
- }
+ mTransaction.setLayer(mSurfaceControl, COLOR_FADE_LAYER)
+ .setAlpha(mSurfaceControl, alpha)
+ .show(mSurfaceControl)
+ .apply();
mSurfaceVisible = true;
mSurfaceAlpha = alpha;
}
diff --git a/services/core/java/com/android/server/integrity/model/EvaluationOutcome.java b/services/core/java/com/android/server/integrity/model/EvaluationOutcome.java
new file mode 100644
index 000000000000..dc30dc39f44a
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/EvaluationOutcome.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+/**
+ * A class encapsulating the result from the evaluation engine after evaluating rules against app
+ * install metadata.
+ *
+ * <p>It contains the outcome effect (whether to allow or block the install), and the rule causing
+ * that effect.
+ */
+public final class EvaluationOutcome {
+
+ public enum Effect {
+ ALLOW,
+ DENY
+ }
+
+ private final Effect mEffect;
+ private final Rule mRule;
+
+ private EvaluationOutcome(Effect effect, Rule rule) {
+ this.mEffect = effect;
+ this.mRule = rule;
+ }
+
+ public Effect getEffect() {
+ return mEffect;
+ }
+
+ public Rule getRule() {
+ return mRule;
+ }
+
+ /**
+ * Create an ALLOW evaluation outcome.
+ *
+ * @return An evaluation outcome with ALLOW effect and empty rule.
+ */
+ public static EvaluationOutcome allow() {
+ return new EvaluationOutcome(Effect.ALLOW, Rule.EMPTY);
+ }
+
+ /**
+ * Create a DENY evaluation outcome.
+ *
+ * @param rule Rule causing the DENY effect.
+ * @return An evaluation outcome with DENY effect and rule causing that effect.
+ */
+ public static EvaluationOutcome deny(Rule rule) {
+ return new EvaluationOutcome(Effect.DENY, rule);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/model/OpenFormula.java b/services/core/java/com/android/server/integrity/model/OpenFormula.java
index 218cdc99c016..e9fa1a370611 100644
--- a/services/core/java/com/android/server/integrity/model/OpenFormula.java
+++ b/services/core/java/com/android/server/integrity/model/OpenFormula.java
@@ -16,9 +16,11 @@
package com.android.server.integrity.model;
+import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.Nullable;
+import java.util.Collections;
+import java.util.List;
/**
* Represents a complex formula consisting of other simple and complex formulas.
@@ -34,46 +36,33 @@ public final class OpenFormula extends Formula {
}
private final Connector mConnector;
- private final Formula mMainFormula;
- private final Formula mAuxiliaryFormula;
+ private final List<Formula> mFormulas;
- public OpenFormula(Connector connector, Formula mainFormula,
- @Nullable Formula auxiliaryFormula) {
- validateAuxiliaryFormula(connector, auxiliaryFormula);
+ public OpenFormula(Connector connector, List<Formula> formulas) {
+ validateFormulas(connector, formulas);
this.mConnector = checkNotNull(connector);
- this.mMainFormula = checkNotNull(mainFormula);
- // TODO: Add validators on auxiliary formula
- this.mAuxiliaryFormula = auxiliaryFormula;
+ this.mFormulas = Collections.unmodifiableList(checkNotNull(formulas));
}
public Connector getConnector() {
return mConnector;
}
- public Formula getMainFormula() {
- return mMainFormula;
+ public List<Formula> getFormulas() {
+ return mFormulas;
}
- public Formula getAuxiliaryFormula() {
- return mAuxiliaryFormula;
- }
-
- private void validateAuxiliaryFormula(Connector connector, Formula auxiliaryFormula) {
- boolean validAuxiliaryFormula;
+ private void validateFormulas(Connector connector, List<Formula> formulas) {
switch (connector) {
case AND:
case OR:
- validAuxiliaryFormula = (auxiliaryFormula != null);
+ checkArgument(formulas.size() >= 2,
+ String.format("Connector %s must have at least 2 formulas", connector));
break;
case NOT:
- validAuxiliaryFormula = (auxiliaryFormula == null);
+ checkArgument(formulas.size() == 1,
+ String.format("Connector %s must have 1 formula only", connector));
break;
- default:
- validAuxiliaryFormula = false;
- }
- if (!validAuxiliaryFormula) {
- throw new IllegalArgumentException(
- String.format("Invalid formulas used for connector %s", connector));
}
}
}
diff --git a/services/core/java/com/android/server/integrity/model/Rule.java b/services/core/java/com/android/server/integrity/model/Rule.java
index 4fd40c1e0365..3d233abda5ed 100644
--- a/services/core/java/com/android/server/integrity/model/Rule.java
+++ b/services/core/java/com/android/server/integrity/model/Rule.java
@@ -25,7 +25,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
*/
public final class Rule {
- enum Effect {
+ public enum Effect {
DENY
}
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 8facce112b52..976cdfbf8f60 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -23,6 +23,7 @@ import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
import static com.android.server.pm.PackageManagerService.fixProcessName;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -219,12 +220,14 @@ public class ComponentResolver {
}
}
+ @Nullable
List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
synchronized (mLock) {
return mActivities.queryIntent(intent, resolvedType, flags, userId);
}
}
+ @Nullable
List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
List<PackageParser.Activity> activities, int userId) {
synchronized (mLock) {
@@ -233,12 +236,14 @@ public class ComponentResolver {
}
}
+ @Nullable
List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
synchronized (mLock) {
return mProviders.queryIntent(intent, resolvedType, flags, userId);
}
}
+ @Nullable
List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
List<PackageParser.Provider> providers, int userId) {
synchronized (mLock) {
@@ -246,6 +251,7 @@ public class ComponentResolver {
}
}
+ @Nullable
List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
int userId) {
if (!sUserManager.exists(userId)) {
@@ -285,6 +291,7 @@ public class ComponentResolver {
return providerList;
}
+ @Nullable
ProviderInfo queryProvider(String authority, int flags, int userId) {
synchronized (mLock) {
final PackageParser.Provider p = mProvidersByAuthority.get(authority);
@@ -326,12 +333,14 @@ public class ComponentResolver {
}
}
+ @Nullable
List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
synchronized (mLock) {
return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
}
+ @Nullable
List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
List<PackageParser.Activity> receivers, int userId) {
synchronized (mLock) {
@@ -339,12 +348,14 @@ public class ComponentResolver {
}
}
+ @Nullable
List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
synchronized (mLock) {
return mServices.queryIntent(intent, resolvedType, flags, userId);
}
}
+ @Nullable
List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
List<PackageParser.Service> services, int userId) {
synchronized (mLock) {
@@ -1355,6 +1366,7 @@ public class ComponentResolver {
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
+ @Nullable
List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
int userId) {
if (!sUserManager.exists(userId)) {
@@ -1366,6 +1378,7 @@ public class ComponentResolver {
userId);
}
+ @Nullable
List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
int flags, List<PackageParser.Provider> packageProviders, int userId) {
if (!sUserManager.exists(userId)) {
diff --git a/core/java/android/content/pm/PackageList.java b/services/core/java/com/android/server/pm/PackageList.java
index e3eb2c55a2bb..60bc8a87f62d 100644
--- a/core/java/android/content/pm/PackageList.java
+++ b/services/core/java/com/android/server/pm/PackageList.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package android.content.pm;
+package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import com.android.server.LocalServices;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e0697a636498..67339c8c8580 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -162,7 +162,6 @@ import android.content.pm.PackageBackwardCompatibility;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstaller;
-import android.content.pm.PackageList;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManager.ModuleInfoFlags;
@@ -3048,7 +3047,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
- mSetupWizardPackage = getSetupWizardPackageName();
+ mSetupWizardPackage = getSetupWizardPackageNameImpl();
mComponentResolver.fixProtectedFilterPriorities();
mSystemTextClassifierPackage = getSystemTextClassifierPackageName();
@@ -6976,7 +6975,7 @@ public class PackageManagerService extends IPackageManager.Stub
* @param intent
* @return A filtered list of resolved activities.
*/
- private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos,
+ private List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
boolean resolveForStart, int userId, Intent intent) {
final boolean blockInstant = intent.isWebIntent() && areWebInstantAppsDisabled(userId);
@@ -7633,6 +7632,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (pkgName == null) {
final List<ResolveInfo> result =
mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
+ if (result == null) {
+ return Collections.emptyList();
+ }
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
intent);
@@ -7641,6 +7643,9 @@ public class PackageManagerService extends IPackageManager.Stub
if (pkg != null) {
final List<ResolveInfo> result = mComponentResolver.queryReceivers(
intent, resolvedType, flags, pkg.receivers, userId);
+ if (result == null) {
+ return Collections.emptyList();
+ }
return applyPostResolutionFilter(
result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
intent);
@@ -7735,15 +7740,25 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
String pkgName = intent.getPackage();
if (pkgName == null) {
+ final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+ resolvedType, flags, userId);
+ if (resolveInfos == null) {
+ return Collections.emptyList();
+ }
return applyPostServiceResolutionFilter(
- mComponentResolver.queryServices(intent, resolvedType, flags, userId),
+ resolveInfos,
instantAppPkgName);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
+ final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent,
+ resolvedType, flags, pkg.services,
+ userId);
+ if (resolveInfos == null) {
+ return Collections.emptyList();
+ }
return applyPostServiceResolutionFilter(
- mComponentResolver.queryServices(intent, resolvedType, flags, pkg.services,
- userId),
+ resolveInfos,
instantAppPkgName);
}
return Collections.emptyList();
@@ -7853,15 +7868,25 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
String pkgName = intent.getPackage();
if (pkgName == null) {
+ final List<ResolveInfo> resolveInfos = mComponentResolver.queryProviders(intent,
+ resolvedType, flags, userId);
+ if (resolveInfos == null) {
+ return Collections.emptyList();
+ }
return applyPostContentProviderResolutionFilter(
- mComponentResolver.queryProviders(intent, resolvedType, flags, userId),
+ resolveInfos,
instantAppPkgName);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
+ final List<ResolveInfo> resolveInfos = mComponentResolver.queryProviders(intent,
+ resolvedType, flags,
+ pkg.providers, userId);
+ if (resolveInfos == null) {
+ return Collections.emptyList();
+ }
return applyPostContentProviderResolutionFilter(
- mComponentResolver.queryProviders(intent, resolvedType, flags,
- pkg.providers, userId),
+ resolveInfos,
instantAppPkgName);
}
return Collections.emptyList();
@@ -19652,7 +19677,7 @@ public class PackageManagerService extends IPackageManager.Stub
set, comp, userId);
}
- private @Nullable String getSetupWizardPackageName() {
+ private @Nullable String getSetupWizardPackageNameImpl() {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_SETUP_WIZARD);
@@ -19759,6 +19784,14 @@ public class PackageManagerService extends IPackageManager.Stub
return systemCaptionsServiceComponentName.getPackageName();
}
+ @Override
+ public String getSetupWizardPackageName() {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Non-system caller");
+ }
+ return mPmInternal.getSetupWizardPackageName();
+ }
+
public String getIncidentReportApproverPackageName() {
return mContext.getString(R.string.config_incidentReportApproverPackage);
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ef31ef151d26..c851cc69a732 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4543,6 +4543,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void wakeUpFromPowerKey(long eventTime) {
wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey,
PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER");
+
+ // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
+ final HdmiControl hdmiControl = getHdmiControl();
+ if (hdmiControl != null) {
+ hdmiControl.turnOnTv();
+ }
}
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 59f051bc76a6..10415f58db80 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -271,11 +271,11 @@ final class AccessibilityController {
}
}
- /** NOTE: This has to be called within a surface transaction. */
- public void drawMagnifiedRegionBorderIfNeededLocked(int displayId) {
+ public void drawMagnifiedRegionBorderIfNeededLocked(int displayId,
+ SurfaceControl.Transaction t) {
final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
if (displayMagnifier != null) {
- displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
+ displayMagnifier.drawMagnifiedRegionBorderIfNeededLocked(t);
}
// Not relevant for the window observer.
}
@@ -431,7 +431,7 @@ final class AccessibilityController {
Slog.i(LOG_TAG, "Rotation: " + Surface.rotationToString(rotation)
+ " displayId: " + displayContent.getDisplayId());
}
- mMagnifedViewport.onRotationChangedLocked();
+ mMagnifedViewport.onRotationChangedLocked(displayContent.getPendingTransaction());
mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
}
@@ -536,9 +536,8 @@ final class AccessibilityController {
.sendToTarget();
}
- /** NOTE: This has to be called within a surface transaction. */
- public void drawMagnifiedRegionBorderIfNeededLocked() {
- mMagnifedViewport.drawWindowIfNeededLocked();
+ public void drawMagnifiedRegionBorderIfNeededLocked(SurfaceControl.Transaction t) {
+ mMagnifedViewport.drawWindowIfNeededLocked(t);
}
private final class MagnifiedViewport {
@@ -744,7 +743,7 @@ final class AccessibilityController {
return letterboxBounds;
}
- public void onRotationChangedLocked() {
+ public void onRotationChangedLocked(SurfaceControl.Transaction t) {
// If we are showing the magnification border, hide it immediately so
// the user does not see strange artifacts during rotation. The screenshot
// used for rotation already has the border. After the rotation is complete
@@ -758,7 +757,7 @@ final class AccessibilityController {
mHandler.sendMessageDelayed(message, delay);
}
recomputeBoundsLocked();
- mWindow.updateSize();
+ mWindow.updateSize(t);
}
public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
@@ -784,10 +783,9 @@ final class AccessibilityController {
return mMagnificationSpec;
}
- /** NOTE: This has to be called within a surface transaction. */
- public void drawWindowIfNeededLocked() {
+ public void drawWindowIfNeededLocked(SurfaceControl.Transaction t) {
recomputeBoundsLocked();
- mWindow.drawIfNeeded();
+ mWindow.drawIfNeeded(t);
}
public void destroyWindow() {
@@ -837,10 +835,11 @@ final class AccessibilityController {
/* ignore */
}
mSurfaceControl = surfaceControl;
- mSurfaceControl.setLayer(mService.mPolicy.getWindowLayerFromTypeLw(
- TYPE_MAGNIFICATION_OVERLAY)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER);
- mSurfaceControl.setPosition(0, 0);
+ mService.mTransactionFactory.get().setLayer(mSurfaceControl,
+ mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER)
+ .setPosition(mSurfaceControl, 0, 0)
+ .apply();
mSurface.copyFrom(mSurfaceControl);
mAnimationController = new AnimationController(context,
@@ -905,10 +904,10 @@ final class AccessibilityController {
}
}
- public void updateSize() {
+ public void updateSize(SurfaceControl.Transaction t) {
synchronized (mService.mGlobalLock) {
mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
- mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
+ t.setBufferSize(mSurfaceControl, mTempPoint.x, mTempPoint.y);
invalidate(mDirtyRect);
}
}
@@ -923,8 +922,7 @@ final class AccessibilityController {
mService.scheduleAnimationLocked();
}
- /** NOTE: This has to be called within a surface transaction. */
- public void drawIfNeeded() {
+ public void drawIfNeeded(SurfaceControl.Transaction t) {
synchronized (mService.mGlobalLock) {
if (!mInvalidated) {
return;
@@ -959,9 +957,9 @@ final class AccessibilityController {
canvas.drawPath(path, mPaint);
mSurface.unlockCanvasAndPost(canvas);
- mSurfaceControl.show();
+ t.show(mSurfaceControl);
} else {
- mSurfaceControl.hide();
+ t.hide(mSurfaceControl);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 976fd52f17e5..4f52d9df817a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1723,25 +1723,27 @@ final class ActivityRecord extends AppWindowToken {
// implied that the current finishing activity should be added into stopping list rather
// than destroy immediately.
final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible);
- final ActivityStack stack = getActivityStack();
- final boolean notFocusedStack = stack != mRootActivityContainer.getTopDisplayFocusedStack();
+ final boolean notGlobalFocusedStack =
+ getActivityStack() != mRootActivityContainer.getTopDisplayFocusedStack();
if (isVisible && isNextNotYetVisible) {
+ // Add this activity to the list of stopping activities. It will be processed and
+ // destroyed when the next activity reports idle.
addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
"completeFinishing");
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (finish requested)");
- }
setState(STOPPING, "completeFinishing");
- if (notFocusedStack) {
+ if (notGlobalFocusedStack) {
+ // Ensuring visibility and configuration only for non-focused stacks since this
+ // method call is relatively expensive and not necessary for focused stacks.
mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
- } else if (isVisible && isState(PAUSED) && getActivityStack().isFocusedStackOnDisplay()
- && !inPinnedWindowingMode()) {
- // TODO(b/137329632): Currently non-focused stack is handled differently.
- addToFinishingAndWaitForIdle();
+ } else if (addToFinishingAndWaitForIdle()) {
+ // We added this activity to the finishing list and something else is becoming resumed.
+ // The activity will complete finishing when the next activity reports idle. No need to
+ // do anything else here.
} else {
- // Not waiting for the next one to become visible - finish right away.
+ // Not waiting for the next one to become visible, and nothing else will be resumed in
+ // place of this activity - requesting destruction right away.
activityRemoved = destroyIfPossible(reason);
}
@@ -1798,13 +1800,20 @@ final class ActivityRecord extends AppWindowToken {
return activityRemoved;
}
+ /**
+ * Add this activity to the list of finishing and trigger resuming of activities in focused
+ * stacks.
+ * @return {@code true} if some other activity is being resumed as a result of this call.
+ */
@VisibleForTesting
- void addToFinishingAndWaitForIdle() {
+ boolean addToFinishingAndWaitForIdle() {
if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
setState(FINISHING, "addToFinishingAndWaitForIdle");
- mStackSupervisor.mFinishingActivities.add(this);
+ if (!mStackSupervisor.mFinishingActivities.contains(this)) {
+ mStackSupervisor.mFinishingActivities.add(this);
+ }
resumeKeyDispatchingLocked();
- mRootActivityContainer.resumeFocusedStacksTopActivities();
+ return mRootActivityContainer.resumeFocusedStacksTopActivities();
}
/**
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b1ef60185d8d..a261341cfa53 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -2930,7 +2930,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
layer += Z_BOOST_BASE;
}
if (!mNeedsAnimationBoundsLayer) {
- leash.setLayer(layer);
+ t.setLayer(leash, layer);
}
final DisplayContent dc = getDisplayContent();
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index c1ca816d788a..b73b481075ae 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -56,7 +56,7 @@ class CircularDisplayMask {
private int mMaskThickness;
CircularDisplayMask(Supplier<Surface> surfaceFactory, DisplayContent dc, int zOrder,
- int screenOffset, int maskThickness) {
+ int screenOffset, int maskThickness, SurfaceControl.Transaction t) {
final Display display = dc.getDisplay();
mSurface = surfaceFactory.get();
mScreenSize = new Point();
@@ -75,10 +75,10 @@ class CircularDisplayMask {
.setFormat(PixelFormat.TRANSLUCENT)
.build();
- ctrl.setLayerStack(display.getLayerStack());
- ctrl.setLayer(zOrder);
- ctrl.setPosition(0, 0);
- ctrl.show();
+ t.setLayerStack(ctrl, display.getLayerStack());
+ t.setLayer(ctrl, zOrder);
+ t.setPosition(ctrl, 0, 0);
+ t.show(ctrl);
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
@@ -91,7 +91,7 @@ class CircularDisplayMask {
mMaskThickness = maskThickness;
}
- private void drawIfNeeded() {
+ private void drawIfNeeded(SurfaceControl.Transaction t) {
if (!mDrawNeeded || !mVisible || mDimensionsUnequal) {
return;
}
@@ -108,45 +108,46 @@ class CircularDisplayMask {
return;
}
switch (mRotation) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_90:
- // chin bottom or right
- mSurfaceControl.setPosition(0, 0);
- break;
- case Surface.ROTATION_180:
- // chin top
- mSurfaceControl.setPosition(0, -mScreenOffset);
- break;
- case Surface.ROTATION_270:
- // chin left
- mSurfaceControl.setPosition(-mScreenOffset, 0);
- break;
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_90:
+ // chin bottom or right
+ t.setPosition(mSurfaceControl, 0, 0);
+ break;
+ case Surface.ROTATION_180:
+ // chin top
+ t.setPosition(mSurfaceControl, 0, -mScreenOffset);
+ break;
+ case Surface.ROTATION_270:
+ // chin left
+ t.setPosition(mSurfaceControl, -mScreenOffset, 0);
+ break;
}
int circleRadius = mScreenSize.x / 2;
c.drawColor(Color.BLACK);
- // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the display edges.
+ // The radius is reduced by mMaskThickness to provide an anti aliasing effect on the
+ // display edges.
c.drawCircle(circleRadius, circleRadius, circleRadius - mMaskThickness, mPaint);
mSurface.unlockCanvasAndPost(c);
}
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
- public void setVisibility(boolean on) {
+ public void setVisibility(boolean on, SurfaceControl.Transaction t) {
if (mSurfaceControl == null) {
return;
}
mVisible = on;
- drawIfNeeded();
+ drawIfNeeded(t);
if (on) {
- mSurfaceControl.show();
+ t.show(mSurfaceControl);
} else {
- mSurfaceControl.hide();
+ t.hide(mSurfaceControl);
}
}
- void positionSurface(int dw, int dh, int rotation) {
+ void positionSurface(int dw, int dh, int rotation, SurfaceControl.Transaction t) {
if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
return;
}
@@ -154,7 +155,7 @@ class CircularDisplayMask {
mLastDH = dh;
mDrawNeeded = true;
mRotation = rotation;
- drawIfNeeded();
+ drawIfNeeded(t);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f592ac6957cb..ac910cde79b0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -331,7 +331,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/**
* For default display it contains real metrics, empty for others.
- * @see WindowManagerService#createWatermarkInTransaction()
+ * @see WindowManagerService#createWatermark()
*/
final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index f64592fd46bd..2165b0e8b593 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -50,7 +50,7 @@ class EmulatorDisplayOverlay {
private boolean mVisible;
EmulatorDisplayOverlay(Supplier<Surface> surfaceFactory, Context context, DisplayContent dc,
- int zOrder) {
+ int zOrder, SurfaceControl.Transaction t) {
mSurface = surfaceFactory.get();
final Display display = dc.getDisplay();
mScreenSize = new Point();
@@ -63,9 +63,9 @@ class EmulatorDisplayOverlay {
.setBufferSize(mScreenSize.x, mScreenSize.y)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
- ctrl.setLayer(zOrder);
- ctrl.setPosition(0, 0);
- ctrl.show();
+ t.setLayer(ctrl, zOrder);
+ t.setPosition(ctrl, 0, 0);
+ t.show(ctrl);
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
@@ -75,7 +75,7 @@ class EmulatorDisplayOverlay {
com.android.internal.R.drawable.emulator_circular_window_overlay);
}
- private void drawIfNeeded() {
+ private void drawIfNeeded(SurfaceControl.Transaction t) {
if (!mDrawNeeded || !mVisible) {
return;
}
@@ -92,7 +92,7 @@ class EmulatorDisplayOverlay {
return;
}
c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
- mSurfaceControl.setPosition(0, 0);
+ t.setPosition(mSurfaceControl, 0, 0);
// Always draw the overlay with square dimensions
int size = Math.max(mScreenSize.x, mScreenSize.y);
mOverlay.setBounds(0, 0, size, size);
@@ -102,20 +102,20 @@ class EmulatorDisplayOverlay {
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
- public void setVisibility(boolean on) {
+ public void setVisibility(boolean on, SurfaceControl.Transaction t) {
if (mSurfaceControl == null) {
return;
}
mVisible = on;
- drawIfNeeded();
+ drawIfNeeded(t);
if (on) {
- mSurfaceControl.show();
+ t.show(mSurfaceControl);
} else {
- mSurfaceControl.hide();
+ t.hide(mSurfaceControl);
}
}
- void positionSurface(int dw, int dh, int rotation) {
+ void positionSurface(int dw, int dh, int rotation, SurfaceControl.Transaction t) {
if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
return;
}
@@ -123,7 +123,7 @@ class EmulatorDisplayOverlay {
mLastDH = dh;
mDrawNeeded = true;
mRotation = rotation;
- drawIfNeeded();
+ drawIfNeeded(t);
}
}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 013607e65367..5d27390da588 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import android.content.ComponentName;
-import android.content.pm.PackageList;
import android.content.pm.PackageManagerInternal;
import android.graphics.Rect;
import android.os.Environment;
@@ -32,6 +31,7 @@ import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import libcore.io.IoUtils;
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 1bd2493e9a07..94d010e846f5 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -247,12 +247,12 @@ public class Letterbox {
mLayoutFrameRelative.offset(-surfaceOrigin.x, -surfaceOrigin.y);
}
- private void createSurface() {
+ private void createSurface(SurfaceControl.Transaction t) {
mSurface = mSurfaceControlFactory.get().setName("Letterbox - " + mType)
.setFlags(HIDDEN).setColorLayer().build();
- mSurface.setLayer(-1);
- mSurface.setColor(new float[]{0, 0, 0});
- mSurface.setColorSpaceAgnostic(true);
+ t.setLayer(mSurface, -1)
+ .setColor(mSurface, new float[]{0, 0, 0})
+ .setColorSpaceAgnostic(mSurface, true);
}
void attachInput(WindowState win) {
@@ -300,7 +300,7 @@ public class Letterbox {
mSurfaceFrameRelative.set(mLayoutFrameRelative);
if (!mSurfaceFrameRelative.isEmpty()) {
if (mSurface == null) {
- createSurface();
+ createSurface(t);
}
t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top);
t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(),
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6f10d3d291b1..b6a05d1b9608 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -813,18 +813,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final int defaultDw = defaultInfo.logicalWidth;
final int defaultDh = defaultInfo.logicalHeight;
if (mWmService.mWatermark != null) {
- mWmService.mWatermark.positionSurface(defaultDw, defaultDh);
+ mWmService.mWatermark.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
}
if (mWmService.mStrictModeFlash != null) {
- mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+ mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, mDisplayTransaction);
}
if (mWmService.mCircularDisplayMask != null) {
mWmService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
- mWmService.getDefaultDisplayRotation());
+ mWmService.getDefaultDisplayRotation(), mDisplayTransaction);
}
if (mWmService.mEmulatorDisplayOverlay != null) {
mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
- mWmService.getDefaultDisplayRotation());
+ mWmService.getDefaultDisplayRotation(), mDisplayTransaction);
}
final int count = mChildren.size();
diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java
index bcd90a14ac96..ba31818d6331 100644
--- a/services/core/java/com/android/server/wm/SeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/SeamlessRotator.java
@@ -20,9 +20,10 @@ import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import android.graphics.Matrix;
+import android.os.IBinder;
import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.Surface.Rotation;
+import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.server.wm.utils.CoordinateTransforms;
@@ -35,7 +36,7 @@ import java.io.StringWriter;
*
* Works by transforming the {@link WindowState} back into the old display rotation.
*
- * Uses {@link android.view.SurfaceControl#deferTransactionUntil(Surface, long)} instead of
+ * Uses {@link Transaction#deferTransactionUntil(SurfaceControl, IBinder, long)} instead of
* latching on the buffer size to allow for seamless 180 degree rotations.
*/
public class SeamlessRotator {
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index 9e5d9cab7669..f537005c955c 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -39,7 +39,8 @@ class StrictModeFlash {
private boolean mDrawNeeded;
private final int mThickness = 20;
- StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc) {
+ StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc,
+ SurfaceControl.Transaction t) {
mSurface = surfaceFactory.get();
SurfaceControl ctrl = null;
try {
@@ -48,9 +49,11 @@ class StrictModeFlash {
.setBufferSize(1, 1)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
- ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101); // one more than Watermark? arbitrary.
- ctrl.setPosition(0, 0);
- ctrl.show();
+
+ // one more than Watermark? arbitrary.
+ t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);
+ t.setPosition(ctrl, 0, 0);
+ t.show(ctrl);
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
@@ -103,25 +106,25 @@ class StrictModeFlash {
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
- public void setVisibility(boolean on) {
+ public void setVisibility(boolean on, SurfaceControl.Transaction t) {
if (mSurfaceControl == null) {
return;
}
drawIfNeeded();
if (on) {
- mSurfaceControl.show();
+ t.show(mSurfaceControl);
} else {
- mSurfaceControl.hide();
+ t.hide(mSurfaceControl);
}
}
- void positionSurface(int dw, int dh) {
+ void positionSurface(int dw, int dh, SurfaceControl.Transaction t) {
if (mLastDW == dw && mLastDH == dh) {
return;
}
mLastDW = dw;
mLastDH = dh;
- mSurfaceControl.setBufferSize(dw, dh);
+ t.setBufferSize(mSurfaceControl, dw, dh);
mDrawNeeded = true;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index d070850a895f..172ebce33668 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -134,6 +134,7 @@ class TaskSnapshotSurface implements StartingSurface {
private final int mStatusBarColor;
@VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
private final int mOrientationOnCreation;
+ private final SurfaceControl.Transaction mTransaction;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
TaskSnapshot snapshot) {
@@ -252,6 +253,7 @@ class TaskSnapshotSurface implements StartingSurface {
windowPrivateFlags, sysUiVis, taskDescription, 1f);
mStatusBarColor = taskDescription.getStatusBarColor();
mOrientationOnCreation = currentOrientation;
+ mTransaction = mService.mTransactionFactory.get();
}
@Override
@@ -336,27 +338,23 @@ class TaskSnapshotSurface implements StartingSurface {
surface.copyFrom(mChildSurfaceControl);
final Rect frame;
- SurfaceControl.openTransaction();
- try {
- // We can just show the surface here as it will still be hidden as the parent is
- // still hidden.
- mChildSurfaceControl.show();
- if (aspectRatioMismatch) {
- // Clip off ugly navigation bar.
- final Rect crop = calculateSnapshotCrop();
- frame = calculateSnapshotFrame(crop);
- mChildSurfaceControl.setWindowCrop(crop);
- mChildSurfaceControl.setPosition(frame.left, frame.top);
- } else {
- frame = null;
- }
-
- // Scale the mismatch dimensions to fill the task bounds
- final float scale = 1 / mSnapshot.getScale();
- mChildSurfaceControl.setMatrix(scale, 0, 0, scale);
- } finally {
- SurfaceControl.closeTransaction();
+ // We can just show the surface here as it will still be hidden as the parent is
+ // still hidden.
+ mTransaction.show(mChildSurfaceControl);
+ if (aspectRatioMismatch) {
+ // Clip off ugly navigation bar.
+ final Rect crop = calculateSnapshotCrop();
+ frame = calculateSnapshotFrame(crop);
+ mTransaction.setWindowCrop(mChildSurfaceControl, crop);
+ mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top);
+ } else {
+ frame = null;
}
+
+ // Scale the mismatch dimensions to fill the task bounds
+ final float scale = 1 / mSnapshot.getScale();
+ mTransaction.setMatrix(mChildSurfaceControl, scale, 0, 0, scale);
+ mTransaction.apply();
surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
surface.release();
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 729cfc04e36c..725aaa48c645 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -55,7 +55,7 @@ class Watermark {
private boolean mDrawNeeded;
Watermark(Supplier<Surface> surfaceFactory, DisplayContent dc, DisplayMetrics dm,
- String[] tokens) {
+ String[] tokens, SurfaceControl.Transaction t) {
if (false) {
Log.i(TAG_WM, "*********************** WATERMARK");
for (int i=0; i<tokens.length; i++) {
@@ -121,21 +121,21 @@ class Watermark {
.setBufferSize(1, 1)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
- ctrl.setLayerStack(mDisplay.getLayerStack());
- ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
- ctrl.setPosition(0, 0);
- ctrl.show();
+ t.setLayerStack(ctrl, mDisplay.getLayerStack())
+ .setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
+ .setPosition(ctrl, 0, 0)
+ .show(ctrl);
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
}
- void positionSurface(int dw, int dh) {
+ void positionSurface(int dw, int dh, SurfaceControl.Transaction t) {
if (mLastDW != dw || mLastDH != dh) {
mLastDW = dw;
mLastDH = dh;
- mSurfaceControl.setBufferSize(dw, dh);
+ t.setBufferSize(mSurfaceControl, dw, dh);
mDrawNeeded = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index f437b284637b..3a1d6e047fa8 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -161,7 +161,8 @@ public class WindowAnimator {
dc.checkAppWindowsReadyToShow();
orAnimating(dc.getDockedDividerController().animate(mCurrentTime));
if (accessibilityController != null) {
- accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId);
+ accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId,
+ mTransaction);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0f4d0a8662f4..6f9f2c0f9708 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1269,14 +1269,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
-
- openSurfaceTransaction();
- try {
- createWatermarkInTransaction();
- } finally {
- closeSurfaceTransaction("createWatermarkInTransaction");
- }
-
+ createWatermark();
showEmulatorDisplayOverlayIfNeeded();
}
@@ -3435,60 +3428,45 @@ public class WindowManagerService extends IWindowManager.Stub
public void showCircularMask(boolean visible) {
synchronized (mGlobalLock) {
+ if (visible) {
+ // TODO(multi-display): support multiple displays
+ if (mCircularDisplayMask == null) {
+ int screenOffset = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_windowOutsetBottom);
+ int maskThickness = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.circular_display_mask_thickness);
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
- ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
- openSurfaceTransaction();
- try {
- if (visible) {
- // TODO(multi-display): support multiple displays
- if (mCircularDisplayMask == null) {
- int screenOffset = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_windowOutsetBottom);
- int maskThickness = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.circular_display_mask_thickness);
-
- mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
- getDefaultDisplayContentLocked(),
- mPolicy.getWindowLayerFromTypeLw(
- WindowManager.LayoutParams.TYPE_POINTER)
- * TYPE_LAYER_MULTIPLIER + 10, screenOffset, maskThickness);
+
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG_WM,
+ ">>> showCircularMask(visible=" + visible + ")");
}
- mCircularDisplayMask.setVisibility(true);
- } else if (mCircularDisplayMask != null) {
- mCircularDisplayMask.setVisibility(false);
- mCircularDisplayMask = null;
+ mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
+ getDefaultDisplayContentLocked(), mPolicy.getWindowLayerFromTypeLw(
+ WindowManager.LayoutParams.TYPE_POINTER) * TYPE_LAYER_MULTIPLIER
+ + 10, screenOffset, maskThickness, mTransaction);
}
- } finally {
- closeSurfaceTransaction("showCircularMask");
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
- "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
+ mCircularDisplayMask.setVisibility(true, mTransaction);
+ } else if (mCircularDisplayMask != null) {
+ mCircularDisplayMask.setVisibility(false, mTransaction);
+ mCircularDisplayMask = null;
}
+ mTransaction.apply();
}
}
public void showEmulatorDisplayOverlay() {
synchronized (mGlobalLock) {
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
- ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
- openSurfaceTransaction();
- try {
- if (mEmulatorDisplayOverlay == null) {
- mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
- mSurfaceFactory,
- mContext,
- getDefaultDisplayContentLocked(),
- mPolicy.getWindowLayerFromTypeLw(
- WindowManager.LayoutParams.TYPE_POINTER)
- * TYPE_LAYER_MULTIPLIER + 10);
- }
- mEmulatorDisplayOverlay.setVisibility(true);
- } finally {
- closeSurfaceTransaction("showEmulatorDisplayOverlay");
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM,
- "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> showEmulatorDisplayOverlay");
+ if (mEmulatorDisplayOverlay == null) {
+ mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(mSurfaceFactory, mContext,
+ getDefaultDisplayContentLocked(),
+ mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
+ * TYPE_LAYER_MULTIPLIER + 10, mTransaction);
}
+ mEmulatorDisplayOverlay.setVisibility(true, mTransaction);
+ mTransaction.apply();
}
}
@@ -3517,23 +3495,16 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
- ">>> OPEN TRANSACTION showStrictModeViolation");
+ if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, ">>> showStrictModeViolation");
// TODO: Modify this to use the surface trace once it is not going crazy.
// b/31532461
- SurfaceControl.openTransaction();
- try {
- // TODO(multi-display): support multiple displays
- if (mStrictModeFlash == null) {
- mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
- getDefaultDisplayContentLocked());
- }
- mStrictModeFlash.setVisibility(on);
- } finally {
- SurfaceControl.closeTransaction();
- if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM,
- "<<< CLOSE TRANSACTION showStrictModeViolation");
+ // TODO(multi-display): support multiple displays
+ if (mStrictModeFlash == null) {
+ mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
+ getDefaultDisplayContentLocked(), mTransaction);
}
+ mStrictModeFlash.setVisibility(on, mTransaction);
+ mTransaction.apply();
}
}
@@ -5520,7 +5491,7 @@ public class WindowManagerService extends IWindowManager.Stub
return val;
}
- void createWatermarkInTransaction() {
+ void createWatermark() {
if (mWatermark != null) {
return;
}
@@ -5538,8 +5509,8 @@ public class WindowManagerService extends IWindowManager.Stub
// TODO(multi-display): Show watermarks on secondary displays.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
mWatermark = new Watermark(mSurfaceFactory, displayContent,
- displayContent.mRealDisplayMetrics,
- toks);
+ displayContent.mRealDisplayMetrics, toks, mTransaction);
+ mTransaction.apply();
}
}
} catch (FileNotFoundException e) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3dcf6ecb5124..1328273c9560 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -506,9 +506,8 @@ class WindowStateAnimator {
flags |= SurfaceControl.OPAQUE;
}
- mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
- attrs.getTitle().toString(), width, height, format, flags, this,
- windowType, ownerUid);
+ mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
+ height, format, flags, this, windowType, ownerUid);
mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 49f27a1b495d..7f68c48e473f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -37,7 +37,6 @@ import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.WindowContentFrameStats;
import com.android.server.protolog.common.ProtoLog;
@@ -85,7 +84,7 @@ class WindowSurfaceController {
private final SurfaceControl.Transaction mTmpTransaction;
- public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
+ WindowSurfaceController(String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
mAnimator = animator;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
index 1a3dde0cb838..2133a7d3550b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
@@ -24,6 +24,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.Arrays;
+import java.util.Collections;
+
@RunWith(JUnit4.class)
public class OpenFormulaTest {
@@ -34,12 +37,11 @@ public class OpenFormulaTest {
@Test
public void testValidOpenFormula() {
- OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.AND, ATOMIC_FORMULA_1,
- ATOMIC_FORMULA_2);
+ OpenFormula openFormula = new OpenFormula(OpenFormula.Connector.AND,
+ Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
assertEquals(OpenFormula.Connector.AND, openFormula.getConnector());
- assertEquals(ATOMIC_FORMULA_1, openFormula.getMainFormula());
- assertEquals(ATOMIC_FORMULA_2, openFormula.getAuxiliaryFormula());
+ assertEquals(Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), openFormula.getFormulas());
}
@Test
@@ -47,9 +49,10 @@ public class OpenFormulaTest {
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format("Invalid formulas used for connector %s", OpenFormula.Connector.AND),
- () -> new OpenFormula(OpenFormula.Connector.AND, ATOMIC_FORMULA_1,
- null));
+ String.format("Connector %s must have at least 2 formulas",
+ OpenFormula.Connector.AND),
+ () -> new OpenFormula(OpenFormula.Connector.AND,
+ Collections.singletonList(ATOMIC_FORMULA_1)));
}
@Test
@@ -57,8 +60,8 @@ public class OpenFormulaTest {
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format("Invalid formulas used for connector %s", OpenFormula.Connector.NOT),
- () -> new OpenFormula(OpenFormula.Connector.NOT, ATOMIC_FORMULA_1,
- ATOMIC_FORMULA_2));
+ String.format("Connector %s must have 1 formula only", OpenFormula.Connector.NOT),
+ () -> new OpenFormula(OpenFormula.Connector.NOT,
+ Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index a98f79cb5369..73420a095cad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -46,7 +46,7 @@ public class DimmerTests extends WindowTestsBase {
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
final SurfaceControl mControl = mock(SurfaceControl.class);
- final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction mTransaction = spy(StubTransaction.class);
TestWindowContainer(WindowManagerService wm) {
super(wm);
@@ -66,7 +66,7 @@ public class DimmerTests extends WindowTestsBase {
private static class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
final SurfaceSession mSession = new SurfaceSession();
final SurfaceControl mHostControl = mock(SurfaceControl.class);
- final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction mHostTransaction = spy(StubTransaction.class);
MockSurfaceBuildingContainer(WindowManagerService wm) {
super(wm);
@@ -118,7 +118,7 @@ public class DimmerTests extends WindowTestsBase {
public void setUp() throws Exception {
mHost = new MockSurfaceBuildingContainer(mWm);
mSurfaceAnimatorStarter = spy(new SurfaceAnimatorStarterImpl());
- mTransaction = mock(SurfaceControl.Transaction.class);
+ mTransaction = spy(StubTransaction.class);
mDimmer = new Dimmer(mHost, mSurfaceAnimatorStarter);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 7115af9f1ee9..b9fef4b008c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -32,7 +32,6 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
import android.content.ComponentName;
-import android.content.pm.PackageList;
import android.content.pm.PackageManagerInternal;
import android.graphics.Rect;
import android.os.UserHandle;
@@ -43,6 +42,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import org.junit.Before;
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index 2d0416d6f5bc..15417d73bd02 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -48,8 +49,8 @@ public class LetterboxTest {
@Before
public void setUp() throws Exception {
mSurfaces = new SurfaceControlMocker();
- mLetterbox = new Letterbox(mSurfaces, () -> mock(SurfaceControl.Transaction.class));
- mTransaction = mock(SurfaceControl.Transaction.class);
+ mLetterbox = new Letterbox(mSurfaces, StubTransaction::new);
+ mTransaction = spy(StubTransaction.class);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index 2ad40f2dc577..f5d08dcfcb77 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -239,4 +239,15 @@ public class StubTransaction extends SurfaceControl.Transaction {
public SurfaceControl.Transaction remove(SurfaceControl sc) {
return this;
}
+
+ @Override
+ public SurfaceControl.Transaction syncInputWindows() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorSpaceAgnostic(SurfaceControl sc, boolean agnostic) {
+ return this;
+ }
+
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
index 778f0ca3c782..9c3ff654ddf0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestActivityDisplay.java
@@ -22,8 +22,11 @@ import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static org.mockito.ArgumentMatchers.any;
+
import android.hardware.display.DisplayManagerGlobal;
import android.view.Display;
import android.view.DisplayInfo;
@@ -85,6 +88,10 @@ class TestActivityDisplay extends ActivityDisplay {
displayRotation.setRotation(rotation);
return true;
}).when(displayRotation).updateRotationUnchecked(anyBoolean());
+
+ final InputMonitor inputMonitor = mDisplayContent.getInputMonitor();
+ spyOn(inputMonitor);
+ doNothing().when(inputMonitor).resumeDispatchingLw(any());
}
@SuppressWarnings("TypeParameterUnusedInFormals")
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
index 0330de8d2c63..bfc07419fd46 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.graphics.Point;
@@ -50,7 +51,7 @@ import org.junit.Test;
@Presubmit
public class WindowAnimationSpecTest {
private final SurfaceControl mSurfaceControl = mock(SurfaceControl.class);
- private final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
+ private final SurfaceControl.Transaction mTransaction = spy(StubTransaction.class);
private final Animation mAnimation = mock(Animation.class);
private final Rect mStackBounds = new Rect(0, 0, 10, 10);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index e5fb28d51fed..a09253ab31f0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -452,7 +452,7 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testSeamlesslyRotateWindow() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
- final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction t = spy(StubTransaction.class);
app.mHasSurface = true;
app.mSurfaceControl = mock(SurfaceControl.class);
@@ -536,7 +536,7 @@ public class WindowStateTests extends WindowTestsBase {
final float[] values = new float[9];
final Matrix matrix = new Matrix();
- final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction t = spy(StubTransaction.class);
final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
win1.mHasSurface = true;
win1.mSurfaceControl = mock(SurfaceControl.class);
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index f4eae8ef4b2a..f4eae8ef4b2a 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 432978d1c866..b7dab161c331 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -35,6 +35,15 @@ public abstract class CellIdentity implements Parcelable {
/** @hide */
public static final int INVALID_CHANNEL_NUMBER = -1;
+ /**
+ * parameters for validation
+ * @hide
+ */
+ public static final int MCC_LENGTH = 3;
+
+ private static final int MNC_MIN_LENGTH = 2;
+ private static final int MNC_MAX_LENGTH = 3;
+
// Log tag
/** @hide */
protected final String mTag;
@@ -207,6 +216,17 @@ public abstract class CellIdentity implements Parcelable {
dest.writeString(mAlphaShort);
}
+ /** Used by phone interface manager to verify if a given string is valid MccMnc
+ * @hide
+ */
+ public static boolean isValidPlmn(@NonNull String plmn) {
+ if (plmn.length() < MCC_LENGTH + MNC_MIN_LENGTH
+ || plmn.length() > MCC_LENGTH + MNC_MAX_LENGTH) {
+ return false;
+ }
+ return (isMcc(plmn.substring(0, MCC_LENGTH)) && isMnc(plmn.substring(MCC_LENGTH)));
+ }
+
/**
* Construct from Parcel
* @hide
@@ -267,10 +287,10 @@ public abstract class CellIdentity implements Parcelable {
/** @hide */
private static boolean isMcc(@NonNull String mcc) {
// ensure no out of bounds indexing
- if (mcc.length() != 3) return false;
+ if (mcc.length() != MCC_LENGTH) return false;
// Character.isDigit allows all unicode digits, not just [0-9]
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < MCC_LENGTH; i++) {
if (mcc.charAt(i) < '0' || mcc.charAt(i) > '9') return false;
}
@@ -280,7 +300,7 @@ public abstract class CellIdentity implements Parcelable {
/** @hide */
private static boolean isMnc(@NonNull String mnc) {
// ensure no out of bounds indexing
- if (mnc.length() < 2 || mnc.length() > 3) return false;
+ if (mnc.length() < MNC_MIN_LENGTH || mnc.length() > MNC_MAX_LENGTH) return false;
// Character.isDigit allows all unicode digits, not just [0-9]
for (int i = 0; i < mnc.length(); i++) {
@@ -289,4 +309,5 @@ public abstract class CellIdentity implements Parcelable {
return true;
}
+
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 66571e39394e..2442023ee27c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6852,6 +6852,40 @@ public class TelephonyManager {
}
/**
+ * Replace the contents of the forbidden PLMN SIM file with the provided values.
+ * Passing an empty list will clear the contents of the EFfplmn file.
+ * If the provided list is shorter than the size of EFfplmn, then the list will be padded
+ * up to the file size with 'FFFFFF'. (required by 3GPP TS 31.102 spec 4.2.16)
+ * If the list is longer than the size of EFfplmn, then the file will be written from the
+ * beginning of the list up to the file size.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @param fplmns a list of PLMNs to be forbidden.
+ *
+ * @return number of PLMNs that were successfully written to the SIM FPLMN list.
+ * This may be less than the number of PLMNs passed in where the SIM file does not have enough
+ * room for all of the values passed in. Return -1 in the event of an unexpected failure
+ */
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public int setForbiddenPlmns(@NonNull List<String> fplmns) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return 0;
+ return telephony.setForbiddenPlmns(
+ getSubId(), APPTYPE_USIM, fplmns, getOpPackageName());
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
+ } catch (NullPointerException ex) {
+ // This could happen before phone starts
+ Rlog.e(TAG, "setForbiddenPlmns NullPointerException: " + ex.getMessage());
+ }
+ return 0;
+ }
+
+ /**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @return array of P-CSCF address
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 28747dab38db..9ff851598648 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -104,7 +104,7 @@ public final class TelephonyScanManager {
private final Looper mLooper;
private final Messenger mMessenger;
- private SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
+ private final SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
public TelephonyScanManager() {
HandlerThread thread = new HandlerThread(TAG);
@@ -204,14 +204,16 @@ public final class TelephonyScanManager {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- int scanId = telephony.requestNetworkScan(
- subId, request, mMessenger, new Binder(), callingPackage);
- if (scanId == INVALID_SCAN_ID) {
- Rlog.e(TAG, "Failed to initiate network scan");
- return null;
+ synchronized (mScanInfo) {
+ int scanId = telephony.requestNetworkScan(
+ subId, request, mMessenger, new Binder(), callingPackage);
+ if (scanId == INVALID_SCAN_ID) {
+ Rlog.e(TAG, "Failed to initiate network scan");
+ return null;
+ }
+ saveScanInfo(scanId, request, executor, callback);
+ return new NetworkScan(scanId, subId);
}
- saveScanInfo(scanId, request, executor, callback);
- return new NetworkScan(scanId, subId);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "requestNetworkScan RemoteException", ex);
@@ -223,9 +225,7 @@ public final class TelephonyScanManager {
private void saveScanInfo(
int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
- synchronized (mScanInfo) {
- mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
- }
+ mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
}
private ITelephony getITelephony() {
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index cabd4dfd91f1..5a90cb13a548 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccCardManager.ResetOption;
import com.android.internal.telephony.euicc.IEuiccController;
@@ -821,17 +822,22 @@ public class EuiccManager {
}
/**
- * Erase all subscriptions and reset the eUICC.
+ * Erase all operational subscriptions and reset the eUICC.
*
* <p>Requires that the calling app has the
* {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
*
* @param callbackIntent a PendingIntent to launch when the operation completes.
+ *
+ * @deprecated From R, callers should specify a flag for specific set of subscriptions to erase
+ * and use @link{eraseSubscriptionsWithOptions} instead
+ *
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
- public void eraseSubscriptions(PendingIntent callbackIntent) {
+ @Deprecated
+ public void eraseSubscriptions(@NonNull PendingIntent callbackIntent) {
if (!isEnabled()) {
sendUnavailableError(callbackIntent);
return;
@@ -844,6 +850,32 @@ public class EuiccManager {
}
/**
+ * Erase all specific subscriptions and reset the eUICC.
+ *
+ * <p>Requires that the calling app has the
+ * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
+ *
+ * @param options flag indicating specific set of subscriptions to erase
+ * @param callbackIntent a PendingIntent to launch when the operation completes.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+ public void eraseSubscriptionsWithOptions(
+ @ResetOption int options, @NonNull PendingIntent callbackIntent) {
+ if (!isEnabled()) {
+ sendUnavailableError(callbackIntent);
+ return;
+ }
+ try {
+ getIEuiccController().eraseSubscriptionsWithOptions(mCardId, options, callbackIntent);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Ensure that subscriptions will be retained on the next factory reset.
*
* <p>By default, all subscriptions on the eUICC are erased the first time a device boots (ever
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4d9057975727..fd7ec561faef 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1612,6 +1612,18 @@ interface ITelephony {
String[] getForbiddenPlmns(int subId, int appType, String callingPackage);
/**
+ * Set the forbidden PLMN list from the givven app type (ex APPTYPE_USIM) on a particular
+ * subscription.
+ *
+ * @param subId subId the id of the subscription
+ * @param appType appType the uicc app type, must be USIM or SIM.
+ * @param fplmns plmns the Forbiden plmns list that needed to be written to the SIM.
+ * @param content callingPackage the op Package name.
+ * @return number of fplmns that is successfully written to the SIM
+ */
+ int setForbiddenPlmns(int subId, int appType, in List<String> fplmns, String callingPackage);
+
+ /**
* Check if phone is in emergency callback mode
* @return true if phone is in emergency callback mode
* @param subId the subscription ID that this action applies to.
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index c9ec0f86a9dc..c19ae7b3916a 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -170,7 +170,7 @@ public class PhoneConstants {
public static final int RIL_CARD_MAX_APPS = 8;
- public static final int DEFAULT_CARD_INDEX = 0;
+ public static final int DEFAULT_SLOT_INDEX = 0;
public static final int MAX_PHONE_COUNT_SINGLE_SIM = 1;
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 20169152539e..7422863d862c 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -44,5 +44,7 @@ interface IEuiccController {
oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
String callingPackage, in PendingIntent callbackIntent);
oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
+ oneway void eraseSubscriptionsWithOptions(
+ int cardId, int options, in PendingIntent callbackIntent);
oneway void retainSubscriptionsForFactoryReset(int cardId, in PendingIntent callbackIntent);
}
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 9c69e2d6e08f..f2d46244d60e 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -22,11 +22,13 @@ import android.graphics.Bitmap;
import android.graphics.Color;
import android.telephony.Rlog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet;
import dalvik.annotation.compat.UnsupportedAppUsage;
import java.io.UnsupportedEncodingException;
+import java.util.List;
/**
* Various methods, useful for dealing with SIM data.
@@ -34,6 +36,11 @@ import java.io.UnsupportedEncodingException;
public class IccUtils {
static final String LOG_TAG="IccUtils";
+ // 3GPP specification constants
+ // Spec reference TS 31.102 section 4.2.16
+ @VisibleForTesting
+ static final int FPLMN_BYTE_SIZE = 3;
+
// A table mapping from a number to a hex character for fast encoding hex strings.
private static final char[] HEX_CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
@@ -896,4 +903,27 @@ public class IccUtils {
}
return 0;
}
+
+ /**
+ * Encode the Fplmns into byte array to write to EF.
+ *
+ * @param fplmns Array of fplmns to be serialized.
+ * @param dataLength the size of the EF file.
+ * @return the encoded byte array in the correct format for FPLMN file.
+ */
+ public static byte[] encodeFplmns(List<String> fplmns, int dataLength) {
+ byte[] serializedFplmns = new byte[dataLength];
+ int offset = 0;
+ for (String fplmn : fplmns) {
+ if (offset >= dataLength) break;
+ stringToBcdPlmn(fplmn, serializedFplmns, offset);
+ offset += FPLMN_BYTE_SIZE;
+ }
+ //pads to the length of the EF file.
+ while (offset < dataLength) {
+ // required by 3GPP TS 31.102 spec 4.2.16
+ serializedFplmns[offset++] = (byte) 0xff;
+ }
+ return serializedFplmns;
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 702921836b0d..3fdba6eac55d 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -54,7 +54,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageList;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
@@ -70,6 +69,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
+import com.android.server.pm.PackageList;
import org.junit.Before;
import org.junit.Test;