Merge "Move blocking surface operations out of lock"
diff --git a/Android.bp b/Android.bp
index 4b82e1d..e1f5abd9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -284,6 +284,7 @@
name: "framework-aidl-export-defaults",
aidl: {
export_include_dirs: [
+ "apex/media/java",
"core/java",
"drm/java",
"graphics/java",
@@ -291,7 +292,6 @@
"location/java",
"lowpan/java",
"media/java",
- "media/apex/java",
"media/mca/effect/java",
"media/mca/filterfw/java",
"media/mca/filterpacks/java",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 78e72bf..4d1ac0e 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -6,6 +6,7 @@
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
cmds/hid/
cmds/input/
+ core/jni/
libs/input/
[Hook Scripts]
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 1ec96ec..9310762 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -81,7 +81,6 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.server.AppStateTracker;
import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
@@ -117,6 +116,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -1283,7 +1283,7 @@
super(context);
mLocalPM = LocalServices.getService(PackageManagerInternal.class);
- mActivityManagerInternal = Preconditions.checkNotNull(
+ mActivityManagerInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
mHandler = new JobHandler(context.getMainLooper());
@@ -1389,7 +1389,7 @@
controller.onSystemServicesReady();
}
- mAppStateTracker = Preconditions.checkNotNull(
+ mAppStateTracker = Objects.requireNonNull(
LocalServices.getService(AppStateTracker.class));
// Register br for package removals and user removals.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 8b61006..aa3d74a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -23,7 +23,6 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
import com.android.server.AppStateTracker;
import com.android.server.AppStateTracker.Listener;
import com.android.server.LocalServices;
@@ -32,6 +31,7 @@
import com.android.server.job.StateControllerProto;
import com.android.server.job.StateControllerProto.BackgroundJobsController.TrackedJob;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -59,7 +59,7 @@
public BackgroundJobsController(JobSchedulerService service) {
super(service);
- mAppStateTracker = Preconditions.checkNotNull(
+ mAppStateTracker = Objects.requireNonNull(
LocalServices.getService(AppStateTracker.class));
mAppStateTracker.addListener(mForceAppStandbyListener);
}
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
new file mode 100644
index 0000000..6bd0086
--- /dev/null
+++ b/apex/media/Android.bp
@@ -0,0 +1,120 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_library {
+ name: "updatable-media",
+
+ srcs: [
+ ":updatable-media-srcs",
+ ],
+
+ aidl: {
+ export_include_dirs: [
+ "java",
+ ],
+
+ // It would be great if we don't need to add include_dirs for public
+ // parcelable classes. Find a better way.
+ include_dirs: [
+ // To refer:
+ // android.os.Bundle
+ // android.os.ResultReceiver
+ "frameworks/base/core/java",
+ ],
+ },
+
+ permitted_packages: [
+ "android.media",
+ ],
+
+ installable: true,
+
+ // TODO: build against stable API surface. Use core_platform for now to avoid
+ // link-check failure with exoplayer building against "current".
+ sdk_version: "core_platform",
+ libs: [
+ // The order matters. android_system_* library should come later.
+ "framework_media_annotation",
+ "android_system_stubs_current",
+ ],
+
+ static_libs: [
+ "exoplayer2-core"
+ ],
+ jarjar_rules: "jarjar_rules.txt",
+
+ plugins: ["java_api_finder"],
+}
+
+filegroup {
+ name: "updatable-media-srcs",
+ srcs: [
+ ":mediaparser-srcs",
+ ":mediasession2-srcs",
+ ],
+}
+
+filegroup {
+ name: "mediasession2-srcs",
+ srcs: [
+ "java/android/media/Controller2Link.java",
+ "java/android/media/IMediaController2.aidl",
+ "java/android/media/IMediaSession2.aidl",
+ "java/android/media/IMediaSession2Service.aidl",
+ "java/android/media/MediaConstants.java",
+ "java/android/media/MediaController2.java",
+ "java/android/media/MediaSession2.java",
+ "java/android/media/MediaSession2Service.java",
+ "java/android/media/Session2Command.java",
+ "java/android/media/Session2CommandGroup.java",
+ "java/android/media/Session2Link.java",
+ "java/android/media/Session2Token.java",
+ ],
+ path: "java",
+}
+
+filegroup {
+ name: "mediaparser-srcs",
+ srcs: [
+ "java/android/media/MediaParser.java"
+ ],
+ path: "java"
+}
+
+droidstubs {
+ name: "updatable-media-stubs",
+ srcs: [
+ ":updatable-media-srcs",
+ ":framework-media-annotation-srcs",
+ ],
+ defaults: [ "framework-module-stubs-defaults-systemapi" ],
+ aidl: {
+ // TODO(b/135922046) remove this
+ include_dirs: ["frameworks/base/core/java"],
+ },
+ sdk_version: "system_current",
+}
+
+java_library {
+ name: "updatable_media_stubs",
+ srcs: [":updatable-media-stubs"],
+ sdk_version: "system_current",
+}
+
+java_library {
+ name: "framework_media_annotation",
+ srcs: [":framework-media-annotation-srcs"],
+ installable: false,
+ sdk_version: "core_current",
+}
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
new file mode 100644
index 0000000..0ac750c
--- /dev/null
+++ b/apex/media/OWNERS
@@ -0,0 +1,4 @@
+andrewlewis@google.com
+dwkang@google.com
+marcone@google.com
+sungsoo@google.com
diff --git a/media/jarjar_rules.txt b/apex/media/jarjar_rules.txt
similarity index 100%
rename from media/jarjar_rules.txt
rename to apex/media/jarjar_rules.txt
diff --git a/media/apex/java/android/media/BufferingParams.java b/apex/media/java/android/media/BufferingParams.java
similarity index 97%
rename from media/apex/java/android/media/BufferingParams.java
rename to apex/media/java/android/media/BufferingParams.java
index 943f142..04af028 100644
--- a/media/apex/java/android/media/BufferingParams.java
+++ b/apex/media/java/android/media/BufferingParams.java
@@ -16,13 +16,9 @@
package android.media;
-import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
/**
* Structure for source buffering management params.
*
diff --git a/media/apex/java/android/media/Controller2Link.aidl b/apex/media/java/android/media/Controller2Link.aidl
similarity index 100%
rename from media/apex/java/android/media/Controller2Link.aidl
rename to apex/media/java/android/media/Controller2Link.aidl
diff --git a/media/apex/java/android/media/Controller2Link.java b/apex/media/java/android/media/Controller2Link.java
similarity index 100%
rename from media/apex/java/android/media/Controller2Link.java
rename to apex/media/java/android/media/Controller2Link.java
diff --git a/media/apex/java/android/media/DataSourceCallback.java b/apex/media/java/android/media/DataSourceCallback.java
similarity index 100%
rename from media/apex/java/android/media/DataSourceCallback.java
rename to apex/media/java/android/media/DataSourceCallback.java
diff --git a/media/apex/java/android/media/IMediaController2.aidl b/apex/media/java/android/media/IMediaController2.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaController2.aidl
rename to apex/media/java/android/media/IMediaController2.aidl
diff --git a/media/apex/java/android/media/IMediaSession2.aidl b/apex/media/java/android/media/IMediaSession2.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaSession2.aidl
rename to apex/media/java/android/media/IMediaSession2.aidl
diff --git a/media/apex/java/android/media/IMediaSession2Service.aidl b/apex/media/java/android/media/IMediaSession2Service.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaSession2Service.aidl
rename to apex/media/java/android/media/IMediaSession2Service.aidl
diff --git a/media/apex/java/android/media/MediaConstants.java b/apex/media/java/android/media/MediaConstants.java
similarity index 100%
rename from media/apex/java/android/media/MediaConstants.java
rename to apex/media/java/android/media/MediaConstants.java
diff --git a/media/apex/java/android/media/MediaController2.java b/apex/media/java/android/media/MediaController2.java
similarity index 100%
rename from media/apex/java/android/media/MediaController2.java
rename to apex/media/java/android/media/MediaController2.java
diff --git a/media/apex/java/android/media/MediaParser.java b/apex/media/java/android/media/MediaParser.java
similarity index 100%
rename from media/apex/java/android/media/MediaParser.java
rename to apex/media/java/android/media/MediaParser.java
diff --git a/media/apex/java/android/media/MediaSession2.java b/apex/media/java/android/media/MediaSession2.java
similarity index 100%
rename from media/apex/java/android/media/MediaSession2.java
rename to apex/media/java/android/media/MediaSession2.java
diff --git a/media/apex/java/android/media/MediaSession2Service.java b/apex/media/java/android/media/MediaSession2Service.java
similarity index 100%
rename from media/apex/java/android/media/MediaSession2Service.java
rename to apex/media/java/android/media/MediaSession2Service.java
diff --git a/media/apex/java/android/media/ProxyDataSourceCallback.java b/apex/media/java/android/media/ProxyDataSourceCallback.java
similarity index 100%
rename from media/apex/java/android/media/ProxyDataSourceCallback.java
rename to apex/media/java/android/media/ProxyDataSourceCallback.java
diff --git a/media/apex/java/android/media/RoutingDelegate.java b/apex/media/java/android/media/RoutingDelegate.java
similarity index 100%
rename from media/apex/java/android/media/RoutingDelegate.java
rename to apex/media/java/android/media/RoutingDelegate.java
diff --git a/media/apex/java/android/media/Session2Command.aidl b/apex/media/java/android/media/Session2Command.aidl
similarity index 100%
rename from media/apex/java/android/media/Session2Command.aidl
rename to apex/media/java/android/media/Session2Command.aidl
diff --git a/media/apex/java/android/media/Session2Command.java b/apex/media/java/android/media/Session2Command.java
similarity index 100%
rename from media/apex/java/android/media/Session2Command.java
rename to apex/media/java/android/media/Session2Command.java
diff --git a/media/apex/java/android/media/Session2CommandGroup.java b/apex/media/java/android/media/Session2CommandGroup.java
similarity index 98%
rename from media/apex/java/android/media/Session2CommandGroup.java
rename to apex/media/java/android/media/Session2CommandGroup.java
index 0ee5f62..13aabfc 100644
--- a/media/apex/java/android/media/Session2CommandGroup.java
+++ b/apex/media/java/android/media/Session2CommandGroup.java
@@ -38,8 +38,8 @@
public final class Session2CommandGroup implements Parcelable {
private static final String TAG = "Session2CommandGroup";
- public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup> CREATOR =
- new Parcelable.Creator<Session2CommandGroup>() {
+ public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup>
+ CREATOR = new Parcelable.Creator<Session2CommandGroup>() {
@Override
public Session2CommandGroup createFromParcel(Parcel in) {
return new Session2CommandGroup(in);
diff --git a/media/apex/java/android/media/Session2Link.java b/apex/media/java/android/media/Session2Link.java
similarity index 100%
rename from media/apex/java/android/media/Session2Link.java
rename to apex/media/java/android/media/Session2Link.java
diff --git a/media/apex/java/android/media/Session2Token.aidl b/apex/media/java/android/media/Session2Token.aidl
similarity index 100%
rename from media/apex/java/android/media/Session2Token.aidl
rename to apex/media/java/android/media/Session2Token.aidl
diff --git a/media/apex/java/android/media/Session2Token.java b/apex/media/java/android/media/Session2Token.java
similarity index 95%
rename from media/apex/java/android/media/Session2Token.java
rename to apex/media/java/android/media/Session2Token.java
index 6eb76b1..aae2e1b 100644
--- a/media/apex/java/android/media/Session2Token.java
+++ b/apex/media/java/android/media/Session2Token.java
@@ -52,17 +52,18 @@
public final class Session2Token implements Parcelable {
private static final String TAG = "Session2Token";
- public static final @android.annotation.NonNull Creator<Session2Token> CREATOR = new Creator<Session2Token>() {
- @Override
- public Session2Token createFromParcel(Parcel p) {
- return new Session2Token(p);
- }
+ public static final @android.annotation.NonNull Creator<Session2Token> CREATOR =
+ new Creator<Session2Token>() {
+ @Override
+ public Session2Token createFromParcel(Parcel p) {
+ return new Session2Token(p);
+ }
- @Override
- public Session2Token[] newArray(int size) {
- return new Session2Token[size];
- }
- };
+ @Override
+ public Session2Token[] newArray(int size) {
+ return new Session2Token[size];
+ }
+ };
/**
* @hide
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 7ed51ca..e4f7300 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -23,7 +23,6 @@
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
@@ -1848,7 +1847,7 @@
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
PowerProfile powerProfile = new PowerProfile(mContext);
- checkNotNull(powerProfile);
+ Objects.requireNonNull(powerProfile);
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
wallClockNanos);
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
index f3bf909..24b7978 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
@@ -95,6 +95,12 @@
return;
}
sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
+ if (sStatsd == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to get stats service.");
+ }
+ return;
+ }
// Assume statsd is ready since this is called form statscompanion, link to statsd.
try {
sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
diff --git a/api/current.txt b/api/current.txt
index c734db5..fca72b1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -610,6 +610,7 @@
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
+ field public static final int featureId = 16844301; // 0x101060d
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillAlpha = 16843980; // 0x10104cc
field public static final int fillBefore = 16843196; // 0x10101bc
@@ -1331,6 +1332,7 @@
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
+ field public static final int supportsInlineSuggestions = 16844302; // 0x101060e
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
field public static final int supportsLocalInteraction = 16844047; // 0x101050f
field public static final int supportsMultipleDisplays = 16844182; // 0x1010596
@@ -4498,7 +4500,6 @@
method public int describeContents();
method @Nullable public String getFeatureId();
method @NonNull public String getMessage();
- method @Nullable public String getNotingPackageName();
method @IntRange(from=0) public int getNotingUid();
method @NonNull public String getOp();
method @IntRange(from=0) public long getTime();
diff --git a/api/system-current.txt b/api/system-current.txt
index 405aab3..b830e37 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -111,6 +111,7 @@
field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
+ field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
@@ -4099,6 +4100,10 @@
method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
}
+ public final class AudioRecordingConfiguration implements android.os.Parcelable {
+ method public int getClientUid();
+ }
+
public class HwAudioSource {
method public boolean isPlaying();
method public void start();
@@ -5693,6 +5698,7 @@
@Deprecated public class WifiConfiguration implements android.os.Parcelable {
method @Deprecated public int getAuthType();
method @Deprecated @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+ method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus();
method @Deprecated @NonNull public String getPrintableSsid();
method @Deprecated @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
@@ -7242,8 +7248,8 @@
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToLuiApp(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void revokeDefaultPermissionsFromLuiApps(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public void setRuntimePermissionsVersion(@IntRange(from=0) int);
- method @RequiresPermission(allOf={android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void startOneTimePermissionSession(@NonNull String, long, int, int);
- method @RequiresPermission(allOf={android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void stopOneTimePermissionSession(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void startOneTimePermissionSession(@NonNull String, long, int, int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS) public void stopOneTimePermissionSession(@NonNull String);
}
public static final class PermissionManager.SplitPermissionInfo {
@@ -7707,7 +7713,9 @@
public static final class Telephony.Carriers implements android.provider.BaseColumns {
field public static final String APN_SET_ID = "apn_set_id";
field public static final int CARRIER_EDITED = 4; // 0x4
+ field @NonNull public static final android.net.Uri DPC_URI;
field public static final String EDITED_STATUS = "edited";
+ field public static final int INVALID_APN_ID = -1; // 0xffffffff
field public static final String MAX_CONNECTIONS = "max_conns";
field public static final String MODEM_PERSIST = "modem_cognitive";
field public static final String MTU = "mtu";
@@ -9763,6 +9771,8 @@
}
public class ServiceState implements android.os.Parcelable {
+ method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
+ method public void fillInNotifierBundle(@NonNull android.os.Bundle);
method public int getDataRegistrationState();
method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
@@ -9771,6 +9781,7 @@
method public int getNrFrequencyRange();
method @Nullable public String getOperatorAlphaLongRaw();
method @Nullable public String getOperatorAlphaShortRaw();
+ method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle);
field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
@@ -9979,6 +9990,7 @@
}
public class TelephonyManager {
+ method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
method public int checkCarrierPrivilegesForPackage(String);
method public int checkCarrierPrivilegesForPackageAnyPhone(String);
@@ -10007,6 +10019,7 @@
method @Deprecated public boolean getDataEnabled(int);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
method @NonNull public static String getDefaultSimCountryIso();
+ method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method public int getEmergencyNumberDbVersion();
@@ -10053,6 +10066,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTetheringApnRequired();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+ method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method public boolean needsOtaServiceProvisioning();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
diff --git a/api/test-current.txt b/api/test-current.txt
index e7153e6..1c1d794 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3249,14 +3249,17 @@
}
public class TelephonyManager {
+ method public int addDevicePolicyOverrideApn(@NonNull android.content.Context, @NonNull android.telephony.data.ApnSetting);
method public int checkCarrierPrivilegesForPackage(String);
method public int getCarrierIdListVersion();
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
+ method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
+ method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
method public void setCarrierTestOverride(String, String, String, String, String, String, String, String, String);
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index a077745..08216d9 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -430,6 +430,6 @@
+ " (Default: touchscreen)");
out.println(" press (Default: trackball)");
out.println(" roll <dx> <dy> (Default: trackball)");
- out.println(" event <DOWN|UP|MOVE> <x> <y> (Default: touchscreen)");
+ out.println(" motionevent <DOWN|UP|MOVE> <x> <y> (Default: touchscreen)");
}
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 887d17c..7b96ce9 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -196,18 +196,6 @@
"libcutils",
"libstatslog",
],
- target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libutils",
- ],
- },
- },
}
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index f9f11b2..109785f 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -152,6 +152,10 @@
return false;
}
+bool HashableDimensionKey::operator!=(const HashableDimensionKey& that) const {
+ return !((*this) == that);
+}
+
bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
if (mValues.size() != that.getValues().size()) {
return false;
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index b9b86ce..654e135 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -71,6 +71,8 @@
std::string toString() const;
+ bool operator!=(const HashableDimensionKey& that) const;
+
bool operator==(const HashableDimensionKey& that) const;
bool operator<(const HashableDimensionKey& that) const;
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 68a51ef..c569bc1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -284,6 +284,10 @@
FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 16c936c..6d2bd04 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -85,5 +85,5 @@
optional bool allow_from_any_uid = 50003 [default = false];
- optional string log_from_module = 50004;
-}
\ No newline at end of file
+ optional string module = 50004;
+}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2270974..19b9709 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -112,9 +112,9 @@
TouchEventReported touch_event_reported = 34;
WakeupAlarmOccurred wakeup_alarm_occurred = 35;
KernelWakeupReported kernel_wakeup_reported = 36;
- WifiLockStateChanged wifi_lock_state_changed = 37 [(log_from_module) = "wifi"];
- WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(log_from_module) = "wifi"];
- WifiScanStateChanged wifi_scan_state_changed = 39 [(log_from_module) = "wifi"];
+ WifiLockStateChanged wifi_lock_state_changed = 37 [(module) = "wifi"];
+ WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(module) = "wifi"];
+ WifiScanStateChanged wifi_scan_state_changed = 39 [(module) = "wifi"];
PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
SettingChanged setting_changed = 41;
ActivityForegroundStateChanged activity_foreground_state_changed = 42;
@@ -128,7 +128,7 @@
AppStartFullyDrawn app_start_fully_drawn = 50;
LmkKillOccurred lmk_kill_occurred = 51;
PictureInPictureStateChanged picture_in_picture_state_changed = 52;
- WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(log_from_module) = "wifi"];
+ WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(module) = "wifi"];
LmkStateChanged lmk_state_changed = 54;
AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
ShutdownSequenceReported shutdown_sequence_reported = 56;
@@ -182,39 +182,27 @@
FlagFlipUpdateOccurred flag_flip_update_occurred = 101;
BinaryPushStateChanged binary_push_state_changed = 102;
DevicePolicyEvent device_policy_event = 103;
- DocsUIFileOperationCanceledReported docs_ui_file_op_canceled =
- 104 [(log_from_module) = "docsui"];
- DocsUIFileOperationCopyMoveModeReported
- docs_ui_file_op_copy_move_mode_reported =
- 105 [(log_from_module) = "docsui"];
- DocsUIFileOperationFailureReported docs_ui_file_op_failure =
- 106 [(log_from_module) = "docsui"];
- DocsUIFileOperationReported docs_ui_provider_file_op =
- 107 [(log_from_module) = "docsui"];
- DocsUIInvalidScopedAccessRequestReported
- docs_ui_invalid_scoped_access_request =
- 108 [(log_from_module) = "docsui"];
- DocsUILaunchReported docs_ui_launch_reported =
- 109 [(log_from_module) = "docsui"];
- DocsUIRootVisitedReported docs_ui_root_visited =
- 110 [(log_from_module) = "docsui"];
- DocsUIStartupMsReported docs_ui_startup_ms =
- 111 [(log_from_module) = "docsui"];
- DocsUIUserActionReported docs_ui_user_action_reported =
- 112 [(log_from_module) = "docsui"];
+ DocsUIFileOperationCanceledReported docs_ui_file_op_canceled = 104 [(module) = "docsui"];
+ DocsUIFileOperationCopyMoveModeReported docs_ui_file_op_copy_move_mode_reported =
+ 105 [(module) = "docsui"];
+ DocsUIFileOperationFailureReported docs_ui_file_op_failure = 106 [(module) = "docsui"];
+ DocsUIFileOperationReported docs_ui_provider_file_op = 107 [(module) = "docsui"];
+ DocsUIInvalidScopedAccessRequestReported docs_ui_invalid_scoped_access_request =
+ 108 [(module) = "docsui"];
+ DocsUILaunchReported docs_ui_launch_reported = 109 [(module) = "docsui"];
+ DocsUIRootVisitedReported docs_ui_root_visited = 110 [(module) = "docsui"];
+ DocsUIStartupMsReported docs_ui_startup_ms = 111 [(module) = "docsui"];
+ DocsUIUserActionReported docs_ui_user_action_reported = 112 [(module) = "docsui"];
WifiEnabledStateChanged wifi_enabled_state_changed = 113;
WifiRunningStateChanged wifi_running_state_changed = 114;
AppCompacted app_compacted = 115;
- NetworkDnsEventReported network_dns_event_reported = 116 [(log_from_module) = "resolv"];
+ NetworkDnsEventReported network_dns_event_reported = 116 [(module) = "resolv"];
DocsUIPickerLaunchedFromReported docs_ui_picker_launched_from_reported =
- 117 [(log_from_module) = "docsui"];
- DocsUIPickResultReported docs_ui_pick_result_reported =
- 118 [(log_from_module) = "docsui"];
- DocsUISearchModeReported docs_ui_search_mode_reported =
- 119 [(log_from_module) = "docsui"];
- DocsUISearchTypeReported docs_ui_search_type_reported =
- 120 [(log_from_module) = "docsui"];
- DataStallEvent data_stall_event = 121 [(log_from_module) = "network_stack"];
+ 117 [(module) = "docsui"];
+ DocsUIPickResultReported docs_ui_pick_result_reported = 118 [(module) = "docsui"];
+ DocsUISearchModeReported docs_ui_search_mode_reported = 119 [(module) = "docsui"];
+ DocsUISearchTypeReported docs_ui_search_type_reported = 120 [(module) = "docsui"];
+ DataStallEvent data_stall_event = 121 [(module) = "network_stack"];
RescuePartyResetReported rescue_party_reset_reported = 122;
SignedConfigReported signed_config_reported = 123;
GnssNiEventReported gnss_ni_event_reported = 124;
@@ -264,7 +252,7 @@
ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
ProcessStartTime process_start_time = 169;
PermissionGrantRequestResultReported permission_grant_request_result_reported =
- 170 [(log_from_module) = "permissioncontroller"];
+ 170 [(module) = "permissioncontroller"];
BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
BubbleDeveloperErrorReported bubble_developer_error_reported = 173;
@@ -273,21 +261,21 @@
AssistGestureProgressReported assist_gesture_progress_reported = 176;
TouchGestureClassified touch_gesture_classified = 177;
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
- StyleUIChanged style_ui_changed = 179 [(log_from_module) = "style"];
+ StyleUIChanged style_ui_changed = 179 [(module) = "style"];
PrivacyIndicatorsInteracted privacy_indicators_interacted =
- 180 [(log_from_module) = "permissioncontroller"];
+ 180 [(module) = "permissioncontroller"];
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
- NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
+ NetworkStackReported network_stack_reported = 182 [(module) = "network_stack"];
AppMovedStorageReported app_moved_storage_reported = 183;
BiometricEnrolled biometric_enrolled = 184;
SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
TombStoneOccurred tomb_stone_occurred = 186;
BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
IntelligenceEventReported intelligence_event_reported =
- 188 [(log_from_module) = "intelligence"];
+ 188 [(module) = "intelligence"];
ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
RoleRequestResultReported role_request_result_reported =
- 190 [(log_from_module) = "permissioncontroller"];
+ 190 [(module) = "permissioncontroller"];
MediametricsAudiopolicyReported mediametrics_audiopolicy_reported = 191;
MediametricsAudiorecordReported mediametrics_audiorecord_reported = 192;
MediametricsAudiothreadReported mediametrics_audiothread_reported = 193;
@@ -301,36 +289,32 @@
MediametricsDrmManagerReported mediametrics_drmmanager_reported = 201;
CarPowerStateChanged car_power_state_changed = 203;
GarageModeInfo garage_mode_info = 204;
- TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
+ TestAtomReported test_atom_reported = 205 [(module) = "cts"];
ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
ContentCaptureServiceEvents content_capture_service_events = 207;
ContentCaptureSessionEvents content_capture_session_events = 208;
ContentCaptureFlushed content_capture_flushed = 209;
LocationManagerApiUsageReported location_manager_api_usage_reported = 210;
ReviewPermissionsFragmentResultReported review_permissions_fragment_result_reported =
- 211 [(log_from_module) = "permissioncontroller"];
+ 211 [(module) = "permissioncontroller"];
RuntimePermissionsUpgradeResult runtime_permissions_upgrade_result =
- 212 [(log_from_module) = "permissioncontroller"];
+ 212 [(module) = "permissioncontroller"];
GrantPermissionsActivityButtonActions grant_permissions_activity_button_actions =
- 213 [(log_from_module) = "permissioncontroller"];
+ 213 [(module) = "permissioncontroller"];
LocationAccessCheckNotificationAction location_access_check_notification_action =
- 214 [(log_from_module) = "permissioncontroller"];
+ 214 [(module) = "permissioncontroller"];
AppPermissionFragmentActionReported app_permission_fragment_action_reported =
- 215 [(log_from_module) = "permissioncontroller"];
+ 215 [(module) = "permissioncontroller"];
AppPermissionFragmentViewed app_permission_fragment_viewed =
- 216 [(log_from_module) = "permissioncontroller"];
+ 216 [(module) = "permissioncontroller"];
AppPermissionsFragmentViewed app_permissions_fragment_viewed =
- 217 [(log_from_module) = "permissioncontroller"];
+ 217 [(module) = "permissioncontroller"];
PermissionAppsFragmentViewed permission_apps_fragment_viewed =
- 218 [(log_from_module) = "permissioncontroller"];
- TextSelectionEvent text_selection_event =
- 219 [(log_from_module) = "textclassifier"];
- TextLinkifyEvent text_linkify_event =
- 220 [(log_from_module) = "textclassifier"];
- ConversationActionsEvent conversation_actions_event =
- 221 [(log_from_module) = "textclassifier"];
- LanguageDetectionEvent language_detection_event =
- 222 [(log_from_module) = "textclassifier"];
+ 218 [(module) = "permissioncontroller"];
+ TextSelectionEvent text_selection_event = 219 [(module) = "textclassifier"];
+ TextLinkifyEvent text_linkify_event = 220 [(module) = "textclassifier"];
+ ConversationActionsEvent conversation_actions_event = 221 [(module) = "textclassifier"];
+ LanguageDetectionEvent language_detection_event = 222 [(module) = "textclassifier"];
ExclusionRectStateChanged exclusion_rect_state_changed = 223;
BackGesture back_gesture_reported_reported = 224;
UpdateEngineUpdateAttemptReported update_engine_update_attempt_reported = 225;
@@ -338,21 +322,17 @@
CameraActionEvent camera_action_event = 227;
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
- PerfettoUploaded perfetto_uploaded =
- 229 [(log_from_module) = "perfetto"];
+ PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
GpsLocationStatusReported gps_location_status_reported = 231;
GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
- MediaProviderScanEvent media_provider_scan_event =
- 233 [(log_from_module) = "mediaprovider"];
- MediaProviderDeletionEvent media_provider_deletion_event =
- 234 [(log_from_module) = "mediaprovider"];
+ MediaProviderScanEvent media_provider_scan_event = 233 [(module) = "mediaprovider"];
+ MediaProviderDeletionEvent media_provider_deletion_event = 234 [(module) = "mediaprovider"];
MediaProviderPermissionEvent media_provider_permission_event =
- 235 [(log_from_module) = "mediaprovider"];
- MediaProviderSchemaChange media_provider_schema_change =
- 236 [(log_from_module) = "mediaprovider"];
+ 235 [(module) = "mediaprovider"];
+ MediaProviderSchemaChange media_provider_schema_change = 236 [(module) = "mediaprovider"];
MediaProviderIdleMaintenance media_provider_idle_maintenance =
- 237 [(log_from_module) = "mediaprovider"];
+ 237 [(module) = "mediaprovider"];
}
// Pulled events will start at field 10000.
@@ -6711,6 +6691,9 @@
// App is not doing pre-rotation correctly.
optional bool false_prerotation = 7;
+
+ // App creates GLESv1 context.
+ optional bool gles_1_in_use = 8;
}
/*
diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp
index d38b87f..3229ba8 100644
--- a/cmds/statsd/src/external/GpuStatsPuller.cpp
+++ b/cmds/statsd/src/external/GpuStatsPuller.cpp
@@ -103,6 +103,7 @@
}
if (!event->write(info.cpuVulkanInUse)) return false;
if (!event->write(info.falsePrerotation)) return false;
+ if (!event->write(info.gles1InUse)) return false;
event->init();
data->emplace_back(event);
}
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index c1f95ee..21ffff3 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -277,8 +277,8 @@
void CountMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
int64_t eventTimeNs = event.GetElapsedTimestampNs();
flushIfNeededLocked(eventTimeNs);
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 7b6c7e0..a4711e8 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -59,8 +59,8 @@
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index fee5e6e..35c6d37 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -541,8 +541,8 @@
void DurationMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKeys, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
ALOGW("Not used in duration tracker.");
}
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 7457d7f..45908fb 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -59,8 +59,8 @@
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKeys, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 32eb077..6833f8d 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -143,8 +143,8 @@
void EventMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
if (!condition) {
return;
}
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index dca37e8..e8f2119 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,8 +47,8 @@
private:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
void onDumpReportLocked(const int64_t dumpTimeNs,
const bool include_current_partial_bucket,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 4ab6ec3..4ab6fd4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -449,8 +449,8 @@
void GaugeMetricProducer::onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) {
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
if (condition == false) {
return;
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 12dcaa4..284bcc5 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -95,8 +95,8 @@
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index cf1d2f3..5c29cb3 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -133,8 +133,8 @@
HashableDimensionKey dimensionInWhat;
filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
MetricDimensionKey metricKey(dimensionInWhat, stateValuesKey);
- onMatchedLogEventInternalLocked(
- matcherIndex, metricKey, conditionKey, condition, event);
+ onMatchedLogEventInternalLocked(matcherIndex, metricKey, conditionKey, condition, event,
+ statePrimaryKeys);
}
bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
@@ -269,6 +269,7 @@
FieldValue* value) {
if (!StateManager::getInstance().getStateValue(atomId, queryKey, value)) {
value->mValue = Value(StateTracker::kStateUnknown);
+ value->mField.setTag(atomId);
ALOGW("StateTracker not found for state atom %d", atomId);
return;
}
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 30675fc..99f0c64 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -330,8 +330,8 @@
*/
virtual void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) = 0;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) = 0;
// Consume the parsed stats log entry that already matched the "what" of the metric.
virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event);
@@ -475,6 +475,10 @@
FRIEND_TEST(StatsLogProcessorTest,
TestActivationOnBootMultipleActivationsDifferentActivationTypes);
FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 1fda696..6d20822 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -289,6 +289,10 @@
FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+ FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index d8f399f..d2db6e9 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -66,6 +66,7 @@
const int FIELD_ID_DIMENSION_IN_WHAT = 1;
const int FIELD_ID_BUCKET_INFO = 3;
const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
+const int FIELD_ID_SLICE_BY_STATE = 6;
// for ValueBucketInfo
const int FIELD_ID_VALUE_INDEX = 1;
const int FIELD_ID_VALUE_LONG = 2;
@@ -146,6 +147,14 @@
mConditionSliced = true;
}
+ for (const auto& stateLink : metric.state_link()) {
+ Metric2State ms;
+ ms.stateAtomId = stateLink.state_atom_id();
+ translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
+ translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
+ mMetric2StateLinks.push_back(ms);
+ }
+
int64_t numBucketsForward = calcBucketsForwardCount(startTimeNs);
mCurrentBucketNum += numBucketsForward;
@@ -181,6 +190,33 @@
}
}
+void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId,
+ const HashableDimensionKey& primaryKey, int oldState,
+ int newState) {
+ VLOG("ValueMetric %lld onStateChanged time %lld, State %d, key %s, %d -> %d",
+ (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(),
+ oldState, newState);
+ // If condition is not true, we do not need to pull for this state change.
+ if (mCondition != ConditionState::kTrue) {
+ return;
+ }
+ bool isEventLate = eventTimeNs < mCurrentBucketStartTimeNs;
+ if (isEventLate) {
+ VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
+ (long long)mCurrentBucketStartTimeNs);
+ invalidateCurrentBucket(eventTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
+ return;
+ }
+ mStateChangePrimaryKey.first = atomId;
+ mStateChangePrimaryKey.second = primaryKey;
+ if (mIsPulled) {
+ pullAndMatchEventsLocked(eventTimeNs);
+ }
+ mStateChangePrimaryKey.first = 0;
+ mStateChangePrimaryKey.second = DEFAULT_DIMENSION_KEY;
+ flushIfNeededLocked(eventTimeNs);
+}
+
void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
const int64_t eventTime) {
VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
@@ -281,6 +317,14 @@
FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
}
+ // Then fill slice_by_state.
+ for (auto state : dimensionKey.getStateValuesKey().getValues()) {
+ uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SLICE_BY_STATE);
+ writeStateToProto(state, protoOutput);
+ protoOutput->end(stateToken);
+ }
+
// Then fill bucket_info (ValueBucketInfo).
for (const auto& bucket : pair.second) {
uint64_t bucketInfoToken = protoOutput->start(
@@ -300,7 +344,7 @@
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_TRUE_NS,
(long long)bucket.mConditionTrueNs);
}
- for (int i = 0; i < (int)bucket.valueIndex.size(); i ++) {
+ for (int i = 0; i < (int)bucket.valueIndex.size(); i++) {
int index = bucket.valueIndex[i];
const Value& value = bucket.values[i];
uint64_t valueToken = protoOutput->start(
@@ -358,9 +402,10 @@
}
void ValueMetricProducer::resetBase() {
- for (auto& slice : mCurrentSlicedBucket) {
- for (auto& interval : slice.second) {
- interval.hasBase = false;
+ for (auto& slice : mCurrentBaseInfo) {
+ for (auto& baseInfo : slice.second) {
+ baseInfo.hasBase = false;
+ baseInfo.hasCurrentState = false;
}
}
mHasGlobalBase = false;
@@ -558,14 +603,20 @@
onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
}
}
- // If the new pulled data does not contains some keys we track in our intervals, we need to
- // reset the base.
+ // If a key that is:
+ // 1. Tracked in mCurrentSlicedBucket and
+ // 2. A superset of the current mStateChangePrimaryKey
+ // was not found in the new pulled data (i.e. not in mMatchedDimensionInWhatKeys)
+ // then we need to reset the base.
for (auto& slice : mCurrentSlicedBucket) {
- bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
- != mMatchedMetricDimensionKeys.end();
- if (!presentInPulledData) {
- for (auto& interval : slice.second) {
- interval.hasBase = false;
+ const auto& whatKey = slice.first.getDimensionKeyInWhat();
+ bool presentInPulledData =
+ mMatchedMetricDimensionKeys.find(whatKey) != mMatchedMetricDimensionKeys.end();
+ if (!presentInPulledData && whatKey.contains(mStateChangePrimaryKey.second)) {
+ auto it = mCurrentBaseInfo.find(whatKey);
+ for (auto& baseInfo : it->second) {
+ baseInfo.hasBase = false;
+ baseInfo.hasCurrentState = false;
}
}
}
@@ -674,17 +725,30 @@
return false;
}
-void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIndex,
- const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey,
- bool condition, const LogEvent& event) {
+void ValueMetricProducer::onMatchedLogEventInternalLocked(
+ const size_t matcherIndex, const MetricDimensionKey& eventKey,
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const map<int, HashableDimensionKey>& statePrimaryKeys) {
+ auto whatKey = eventKey.getDimensionKeyInWhat();
+ auto stateKey = eventKey.getStateValuesKey();
+
+ // Skip this event if a state changed occurred for a different primary key.
+ auto it = statePrimaryKeys.find(mStateChangePrimaryKey.first);
+ // Check that both the atom id and the primary key are equal.
+ if (it != statePrimaryKeys.end() && it->second != mStateChangePrimaryKey.second) {
+ VLOG("ValueMetric skip event with primary key %s because state change primary key "
+ "is %s",
+ it->second.toString().c_str(), mStateChangePrimaryKey.second.toString().c_str());
+ return;
+ }
+
int64_t eventTimeNs = event.GetElapsedTimestampNs();
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
return;
}
- mMatchedMetricDimensionKeys.insert(eventKey);
+ mMatchedMetricDimensionKeys.insert(whatKey);
if (!mIsPulled) {
// We cannot flush without doing a pull first.
@@ -709,10 +773,26 @@
if (hitGuardRailLocked(eventKey)) {
return;
}
- vector<Interval>& multiIntervals = mCurrentSlicedBucket[eventKey];
- if (multiIntervals.size() < mFieldMatchers.size()) {
+ vector<BaseInfo>& baseInfos = mCurrentBaseInfo[whatKey];
+ if (baseInfos.size() < mFieldMatchers.size()) {
VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
- multiIntervals.resize(mFieldMatchers.size());
+ baseInfos.resize(mFieldMatchers.size());
+ }
+
+ for (auto baseInfo : baseInfos) {
+ if (!baseInfo.hasCurrentState) {
+ baseInfo.currentState = DEFAULT_DIMENSION_KEY;
+ baseInfo.hasCurrentState = true;
+ }
+ }
+
+ // We need to get the intervals stored with the previous state key so we can
+ // close these value intervals.
+ const auto oldStateKey = baseInfos[0].currentState;
+ vector<Interval>& intervals = mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)];
+ if (intervals.size() < mFieldMatchers.size()) {
+ VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
+ intervals.resize(mFieldMatchers.size());
}
// We only use anomaly detection under certain cases.
@@ -725,7 +805,8 @@
for (int i = 0; i < (int)mFieldMatchers.size(); i++) {
const Matcher& matcher = mFieldMatchers[i];
- Interval& interval = multiIntervals[i];
+ BaseInfo& baseInfo = baseInfos[i];
+ Interval& interval = intervals[i];
interval.valueIndex = i;
Value value;
if (!getDoubleOrLong(event, matcher, value)) {
@@ -736,60 +817,61 @@
interval.seenNewData = true;
if (mUseDiff) {
- if (!interval.hasBase) {
+ if (!baseInfo.hasBase) {
if (mHasGlobalBase && mUseZeroDefaultBase) {
// The bucket has global base. This key does not.
// Optionally use zero as base.
- interval.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
- interval.hasBase = true;
+ baseInfo.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
+ baseInfo.hasBase = true;
} else {
// no base. just update base and return.
- interval.base = value;
- interval.hasBase = true;
+ baseInfo.base = value;
+ baseInfo.hasBase = true;
// If we're missing a base, do not use anomaly detection on incomplete data
useAnomalyDetection = false;
- // Continue (instead of return) here in order to set interval.base and
- // interval.hasBase for other intervals
+ // Continue (instead of return) here in order to set baseInfo.base and
+ // baseInfo.hasBase for other baseInfos
continue;
}
}
+
Value diff;
switch (mValueDirection) {
case ValueMetric::INCREASING:
- if (value >= interval.base) {
- diff = value - interval.base;
+ if (value >= baseInfo.base) {
+ diff = value - baseInfo.base;
} else if (mUseAbsoluteValueOnReset) {
diff = value;
} else {
VLOG("Unexpected decreasing value");
StatsdStats::getInstance().notePullDataError(mPullTagId);
- interval.base = value;
+ baseInfo.base = value;
// If we've got bad data, do not use anomaly detection
useAnomalyDetection = false;
continue;
}
break;
case ValueMetric::DECREASING:
- if (interval.base >= value) {
- diff = interval.base - value;
+ if (baseInfo.base >= value) {
+ diff = baseInfo.base - value;
} else if (mUseAbsoluteValueOnReset) {
diff = value;
} else {
VLOG("Unexpected increasing value");
StatsdStats::getInstance().notePullDataError(mPullTagId);
- interval.base = value;
+ baseInfo.base = value;
// If we've got bad data, do not use anomaly detection
useAnomalyDetection = false;
continue;
}
break;
case ValueMetric::ANY:
- diff = value - interval.base;
+ diff = value - baseInfo.base;
break;
default:
break;
}
- interval.base = value;
+ baseInfo.base = value;
value = diff;
}
@@ -814,12 +896,13 @@
interval.hasValue = true;
}
interval.sampleSize += 1;
+ baseInfo.currentState = stateKey;
}
// Only trigger the tracker if all intervals are correct
if (useAnomalyDetection) {
// TODO: propgate proper values down stream when anomaly support doubles
- long wholeBucketVal = multiIntervals[0].value.long_value;
+ long wholeBucketVal = intervals[0].value.long_value;
auto prev = mCurrentFullBucket.find(eventKey);
if (prev != mCurrentFullBucket.end()) {
wholeBucketVal += prev->second;
@@ -953,6 +1036,7 @@
} else {
it++;
}
+ // TODO: remove mCurrentBaseInfo entries when obsolete
}
mCurrentBucketIsInvalid = false;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 4eae99b..19fb694 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -83,11 +83,14 @@
flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
+ void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
+ int oldState, int newState) override;
+
protected:
void onMatchedLogEventInternalLocked(
const size_t matcherIndex, const MetricDimensionKey& eventKey,
- const ConditionKey& conditionKey, bool condition,
- const LogEvent& event) override;
+ const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+ const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
private:
void onDumpReportLocked(const int64_t dumpTimeNs,
@@ -144,7 +147,10 @@
std::vector<Matcher> mFieldMatchers;
// Value fields for matching.
- std::set<MetricDimensionKey> mMatchedMetricDimensionKeys;
+ std::set<HashableDimensionKey> mMatchedMetricDimensionKeys;
+
+ // Holds the atom id, primary key pair from a state change.
+ pair<int32_t, HashableDimensionKey> mStateChangePrimaryKey;
// tagId for pulled data. -1 if this is not pulled
const int mPullTagId;
@@ -156,10 +162,6 @@
typedef struct {
// Index in multi value aggregation.
int valueIndex;
- // Holds current base value of the dimension. Take diff and update if necessary.
- Value base;
- // Whether there is a base to diff to.
- bool hasBase;
// Current value, depending on the aggregation type.
Value value;
// Number of samples collected.
@@ -171,8 +173,21 @@
bool seenNewData = false;
} Interval;
+ typedef struct {
+ // Holds current base value of the dimension. Take diff and update if necessary.
+ Value base;
+ // Whether there is a base to diff to.
+ bool hasBase;
+ // Last seen state value(s).
+ HashableDimensionKey currentState;
+ // Whether this dimensions in what key has a current state key.
+ bool hasCurrentState;
+ } BaseInfo;
+
std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
+ std::unordered_map<HashableDimensionKey, std::vector<BaseInfo>> mCurrentBaseInfo;
+
std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
// Save the past buckets and we can clear when the StatsLogReport is dumped.
@@ -285,6 +300,9 @@
FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedState);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithMap);
+ FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions);
FRIEND_TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBase);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 2ad8217..73c1212 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -18,11 +18,12 @@
#include "Log.h"
#include "metrics_manager_util.h"
-#include "MetricProducer.h"
#include <inttypes.h>
#include "atoms_info.h"
+#include "FieldValue.h"
+#include "MetricProducer.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "condition/StateConditionTracker.h"
@@ -173,6 +174,14 @@
return true;
}
+bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
+ const vector<Matcher>& dimensionsInWhat) {
+ vector<Matcher> stateMatchers;
+ translateFieldMatcher(stateMatcher, &stateMatchers);
+
+ return subsetDimensions(stateMatchers, dimensionsInWhat);
+}
+
// 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.
@@ -669,18 +678,41 @@
}
}
+ std::vector<int> slicedStateAtoms;
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ if (metric.slice_by_state_size() > 0) {
+ if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ return false;
+ }
+ } else {
+ if (metric.state_link_size() > 0) {
+ ALOGW("ValueMetric has a MetricStateLink but doesn't have a sliced state");
+ return false;
+ }
+ }
+
+ // Check that all metric state links are a subset of dimensions_in_what fields.
+ std::vector<Matcher> dimensionsInWhat;
+ translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+ for (const auto& stateLink : metric.state_link()) {
+ if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+ return false;
+ }
+ }
+
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);
+ 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, eventActivationMap,
- eventDeactivationMap);
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
allMetricProducers.push_back(valueProducer);
}
diff --git a/cmds/statsd/src/state/StateManager.cpp b/cmds/statsd/src/state/StateManager.cpp
index 80d3983..ea776fa 100644
--- a/cmds/statsd/src/state/StateManager.cpp
+++ b/cmds/statsd/src/state/StateManager.cpp
@@ -28,13 +28,17 @@
return sStateManager;
}
+void StateManager::clear() {
+ mStateTrackers.clear();
+}
+
void StateManager::onLogEvent(const LogEvent& event) {
if (mStateTrackers.find(event.GetTagId()) != mStateTrackers.end()) {
mStateTrackers[event.GetTagId()]->onLogEvent(event);
}
}
-bool StateManager::registerListener(int32_t atomId, wp<StateListener> listener) {
+bool StateManager::registerListener(const int32_t atomId, wp<StateListener> listener) {
// Check if state tracker already exists.
if (mStateTrackers.find(atomId) == mStateTrackers.end()) {
// Create a new state tracker iff atom is a state atom.
@@ -50,7 +54,7 @@
return true;
}
-void StateManager::unregisterListener(int32_t atomId, wp<StateListener> listener) {
+void StateManager::unregisterListener(const int32_t atomId, wp<StateListener> listener) {
std::unique_lock<std::mutex> lock(mMutex);
// Hold the sp<> until the lock is released so that ~StateTracker() is
@@ -74,7 +78,7 @@
lock.unlock();
}
-bool StateManager::getStateValue(int32_t atomId, const HashableDimensionKey& key,
+bool StateManager::getStateValue(const int32_t atomId, const HashableDimensionKey& key,
FieldValue* output) const {
auto it = mStateTrackers.find(atomId);
if (it != mStateTrackers.end()) {
diff --git a/cmds/statsd/src/state/StateManager.h b/cmds/statsd/src/state/StateManager.h
index a6053e6..8bc2461 100644
--- a/cmds/statsd/src/state/StateManager.h
+++ b/cmds/statsd/src/state/StateManager.h
@@ -40,30 +40,33 @@
// Returns a pointer to the single, shared StateManager object.
static StateManager& getInstance();
+ // Unregisters all listeners and removes all trackers from StateManager.
+ void clear();
+
// Notifies the correct StateTracker of an event.
void onLogEvent(const LogEvent& event);
// Returns true if atomId is being tracked and is associated with a state
// atom. StateManager notifies the correct StateTracker to register listener.
// If the correct StateTracker does not exist, a new StateTracker is created.
- bool registerListener(int32_t atomId, wp<StateListener> listener);
+ bool registerListener(const int32_t atomId, wp<StateListener> listener);
// Notifies the correct StateTracker to unregister a listener
// and removes the tracker if it no longer has any listeners.
- void unregisterListener(int32_t atomId, wp<StateListener> listener);
+ void unregisterListener(const int32_t atomId, wp<StateListener> listener);
// Returns true if the StateTracker exists and queries for the
// original state value mapped to the given query key. The state value is
// stored and output in a FieldValue class.
// Returns false if the StateTracker doesn't exist.
- bool getStateValue(int32_t atomId, const HashableDimensionKey& queryKey,
+ bool getStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
FieldValue* output) const;
inline int getStateTrackersCount() const {
return mStateTrackers.size();
}
- inline int getListenersCount(int32_t atomId) const {
+ inline int getListenersCount(const int32_t atomId) const {
auto it = mStateTrackers.find(atomId);
if (it != mStateTrackers.end()) {
return it->second->getListenersCount();
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 8b4d781..c45274e 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -147,12 +147,14 @@
message ValueMetricData {
optional DimensionsValue dimensions_in_what = 1;
- optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+ repeated StateValue slice_by_state = 6;
repeated ValueBucketInfo bucket_info = 3;
repeated DimensionsValue dimension_leaf_values_in_what = 4;
+ optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+
repeated DimensionsValue dimension_leaf_values_in_condition = 5 [deprecated = true];
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index a22805b..736aa9b 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -290,12 +290,14 @@
optional FieldMatcher dimensions_in_what = 5;
- optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
+ repeated int64 slice_by_state = 18;
optional TimeUnit bucket = 6;
repeated MetricConditionLink links = 7;
+ repeated MetricStateLink state_link = 19;
+
enum AggregationType {
SUM = 1;
MIN = 2;
@@ -325,6 +327,8 @@
optional int32 max_pull_delay_sec = 16 [default = 10];
optional bool split_bucket_for_app_upgrade = 17 [default = true];
+
+ optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
}
message Alert {
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 0f51c1b..15fc468 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -27,9 +27,6 @@
#ifdef __ANDROID__
-const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
-const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
-
/**
* Test a count metric that has one slice_by_state with no primary fields.
*
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index fb878dc7..e8d2ec5 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -369,6 +369,168 @@
EXPECT_EQ(1, bucketInfo.values_size());
}
+/**
+ * Test initialization of a simple value metric that is sliced by a state.
+ *
+ * ValueCpuUserTimePerScreenState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto pulledAtomMatcher =
+ CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ *config.add_atom_matcher() = pulledAtomMatcher;
+
+ auto screenState = CreateScreenState();
+ *config.add_state() = screenState;
+
+ // Create value metric that slices by screen state without a map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(pulledAtomMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ valueMetric->add_slice_by_state(screenState.id());
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ const uint64_t bucketSizeNs =
+ TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000LL;
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // Check that StateTrackers were initialized correctly.
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Check that ValueMetricProducer was initialized correctly.
+ EXPECT_EQ(1U, processor->mMetricsManagers.size());
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+ EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto cpuTimePerUidMatcher =
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+ auto uidProcessState = CreateUidProcessState();
+ *config.add_state() = uidProcessState;
+
+ // Create value metric that slices by screen state with a complete map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(cpuTimePerUidMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ *valueMetric->mutable_dimensions_in_what() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ valueMetric->add_slice_by_state(uidProcessState.id());
+ MetricStateLink* stateLink = valueMetric->add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // Check that StateTrackers were initialized correctly.
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+ // Check that ValueMetricProducer was initialized correctly.
+ EXPECT_EQ(1U, processor->mMetricsManagers.size());
+ sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+ EXPECT_TRUE(metricsManager->isConfigValid());
+ EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+ sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+ EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+ EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions) {
+ // Create config.
+ StatsdConfig config;
+ config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+
+ auto cpuTimePerUidMatcher =
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+ auto uidProcessState = CreateUidProcessState();
+ *config.add_state() = uidProcessState;
+
+ // Create value metric that slices by screen state with a complete map.
+ int64_t metricId = 123456;
+ auto valueMetric = config.add_value_metric();
+ valueMetric->set_id(metricId);
+ valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+ valueMetric->set_what(cpuTimePerUidMatcher.id());
+ *valueMetric->mutable_value_field() =
+ CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ valueMetric->add_slice_by_state(uidProcessState.id());
+ MetricStateLink* stateLink = valueMetric->add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+ valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+ // Initialize StatsLogProcessor.
+ const uint64_t bucketStartTimeNs = 10000000000; // 0:10
+ int uid = 12345;
+ int64_t cfgId = 98765;
+ ConfigKey cfgKey(uid, cfgId);
+ auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+ // No StateTrackers are initialized.
+ EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
+
+ // Config initialization fails.
+ EXPECT_EQ(0, processor->mMetricsManagers.size());
+}
+
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
index 6abdfa3..ae92705 100644
--- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
@@ -58,8 +58,9 @@
static const int32_t GLES_VERSION = 3;
static const bool CPU_VULKAN_IN_USE = true;
static const bool FALSE_PREROTATION = true;
+static const bool GLES_1_IN_USE = true;
static const size_t NUMBER_OF_VALUES_GLOBAL = 13;
-static const size_t NUMBER_OF_VALUES_APP = 7;
+static const size_t NUMBER_OF_VALUES_APP = 8;
// clang-format on
class MockGpuStatsPuller : public GpuStatsPuller {
@@ -153,6 +154,7 @@
EXPECT_TRUE(event->write(int64VectorToProtoByteString(angleDriverLoadingTime)));
EXPECT_TRUE(event->write(CPU_VULKAN_IN_USE));
EXPECT_TRUE(event->write(FALSE_PREROTATION));
+ EXPECT_TRUE(event->write(GLES_1_IN_USE));
event->init();
inData.emplace_back(event);
MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData);
@@ -172,6 +174,7 @@
outData[0]->getValues()[4].mValue.str_value);
EXPECT_EQ(CPU_VULKAN_IN_USE, outData[0]->getValues()[5].mValue.int_value);
EXPECT_EQ(FALSE_PREROTATION, outData[0]->getValues()[6].mValue.int_value);
+ EXPECT_EQ(GLES_1_IN_USE, outData[0]->getValues()[7].mValue.int_value);
}
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index da0a672..92e8241 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -148,6 +148,26 @@
return valueProducer;
}
+ static sp<ValueMetricProducer> createValueProducerWithState(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+ vector<int32_t> slicedStateAtoms,
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+ {}, slicedStateAtoms, stateGroupMap);
+ return valueProducer;
+ }
+
static ValueMetric createMetric() {
ValueMetric metric;
metric.set_id(metricId);
@@ -163,8 +183,13 @@
metric.set_condition(StringToId("SCREEN_ON"));
return metric;
}
-};
+ static ValueMetric createMetricWithState(string state) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.add_slice_by_state(StringToId(state));
+ return metric;
+ }
+};
/*
* Tests that the first bucket works correctly
@@ -253,10 +278,12 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -273,9 +300,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(12, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -294,9 +322,10 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(13, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -394,9 +423,8 @@
}));
sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
- kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -411,9 +439,10 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -430,8 +459,8 @@
// No new data seen, so data has been cleared.
EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -447,10 +476,11 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// the base was reset
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
@@ -482,9 +512,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -498,8 +529,9 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -515,8 +547,9 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -549,9 +582,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -565,8 +599,9 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -579,8 +614,9 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -633,9 +669,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -652,8 +689,9 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(110, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(110, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
@@ -663,9 +701,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
@@ -879,6 +918,7 @@
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(10, curInterval.value.long_value);
EXPECT_EQ(true, curInterval.hasValue);
@@ -1066,10 +1106,11 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:true sum:0 start:11
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(11, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1084,9 +1125,10 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// tartUpdated:false sum:12
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(23, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
@@ -1103,9 +1145,10 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:12
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(36, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
}
@@ -1148,16 +1191,18 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
// Now the alarm is delivered.
// since the condition turned to off before this pull finish, it has no effect
@@ -1167,7 +1212,8 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -1220,9 +1266,10 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// startUpdated:false sum:0 start:100
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1231,15 +1278,17 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
// condition changed to true again, before the pull alarm is delivered
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(130, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(130, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
// Now the alarm is delivered, but it is considered late, the data will be used
@@ -1249,8 +1298,9 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
@@ -1477,8 +1527,9 @@
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(10, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
@@ -1497,8 +1548,9 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(15, curInterval.base.long_value);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
@@ -1508,8 +1560,9 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(15, curInterval.base.long_value);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
@@ -1550,27 +1603,29 @@
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval0 =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
- ValueMetricProducer::Interval curInterval1 =
- valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(10, curInterval0.base.long_value);
- EXPECT_EQ(false, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(20, curInterval1.base.long_value);
- EXPECT_EQ(false, curInterval1.hasValue);
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(20, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
// has one slice
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(5, curInterval0.value.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
- EXPECT_EQ(2, curInterval1.value.long_value);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(5, curInterval.value.long_value);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(2, curInterval.value.long_value);
// no change in first value field
shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
@@ -1580,14 +1635,17 @@
event3->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(15, curInterval0.base.long_value);
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(25, curInterval1.base.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(25, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
event4->write(1);
@@ -1596,14 +1654,16 @@
event4->init();
valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
- EXPECT_EQ(true, curInterval0.hasBase);
- EXPECT_EQ(15, curInterval0.base.long_value);
- EXPECT_EQ(true, curInterval0.hasValue);
- EXPECT_EQ(true, curInterval1.hasBase);
- EXPECT_EQ(29, curInterval1.base.long_value);
- EXPECT_EQ(true, curInterval1.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(29, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
@@ -1650,9 +1710,11 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
+ auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+ auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1672,8 +1734,8 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
@@ -1683,11 +1745,19 @@
break;
}
}
+ auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ if (itBase != iterBase) {
+ break;
+ }
+ }
EXPECT_TRUE(it != iter);
+ EXPECT_TRUE(itBase != iterBase);
auto& interval2 = it->second[0];
+ auto& baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
@@ -1725,11 +1795,13 @@
ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- auto iter = valueProducer->mCurrentSlicedBucket.begin();
- auto& interval1 = iter->second[0];
- EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto& interval1 = it->second[0];
+ auto& baseInfo1 =
+ valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1749,22 +1821,31 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer->mCurrentSlicedBucket.begin();
- for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
- if (it != iter) {
+ auto it2 = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
+ if (it2 != it) {
break;
}
}
- EXPECT_TRUE(it != iter);
- auto& interval2 = it->second[0];
- EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ // auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ // if (itBase != iterBase) {
+ // break;
+ // }
+ // }
+ EXPECT_TRUE(it2 != it);
+ // EXPECT_TRUE(itBase != iterBase);
+ auto& interval2 = it2->second[0];
+ auto& baseInfo2 =
+ valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+ EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1779,8 +1860,8 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(5, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(5, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1799,17 +1880,24 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0];
- EXPECT_EQ(true, it1.hasBase);
- EXPECT_EQ(13, it1.base.long_value);
- EXPECT_EQ(false, it1.hasValue);
- EXPECT_EQ(8, it1.value.long_value);
- auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, it2.hasBase);
- EXPECT_EQ(5, it2.base.long_value);
- EXPECT_EQ(false, it2.hasValue);
- EXPECT_EQ(5, it2.value.long_value);
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
+ interval1 = it->second[0];
+ interval2 = it2->second[0];
+ baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(5, baseInfo1.base.long_value);
+ EXPECT_EQ(false, interval1.hasValue);
+ EXPECT_EQ(5, interval1.value.long_value);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(13, baseInfo2.base.long_value);
+ EXPECT_EQ(false, interval2.hasValue);
+ EXPECT_EQ(8, interval2.value.long_value);
+
EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
}
@@ -1839,9 +1927,11 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
+ auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+ auto& baseInfo1 = iterBase->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(3, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(3, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
@@ -1860,8 +1950,8 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(11, interval1.base.long_value);
+ EXPECT_EQ(true, baseInfo1.hasBase);
+ EXPECT_EQ(11, baseInfo1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
EXPECT_FALSE(interval1.seenNewData);
@@ -1873,11 +1963,19 @@
break;
}
}
+ auto itBase = valueProducer->mCurrentBaseInfo.begin();
+ for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+ if (itBase != iterBase) {
+ break;
+ }
+ }
EXPECT_TRUE(it != iter);
+ EXPECT_TRUE(itBase != iterBase);
auto& interval2 = it->second[0];
+ auto& baseInfo2 = itBase->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(4, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1890,12 +1988,13 @@
event1->init();
allData.push_back(event1);
valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- // Only one interval left. One was trimmed.
+ // Only one interval left. One was trimmed.
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(5, interval2.base.long_value);
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(5, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1909,8 +2008,9 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(14, interval2.base.long_value);
+ baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, baseInfo2.hasBase);
+ EXPECT_EQ(14, baseInfo2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1946,14 +2046,15 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
vector<shared_ptr<LogEvent>> allData;
valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -1983,8 +2084,9 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1993,7 +2095,7 @@
// has one slice
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, curInterval.hasBase);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2035,7 +2137,8 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2118,8 +2221,9 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(100, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
@@ -2181,8 +2285,9 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2222,7 +2327,8 @@
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
for (int i = 0; i < 2000; i++) {
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+ shared_ptr<LogEvent> event =
+ make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
event->write(i);
event->write(i);
event->init();
@@ -2338,8 +2444,9 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(140, curInterval.base.long_value);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2429,7 +2536,8 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
@@ -2523,7 +2631,8 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2531,7 +2640,8 @@
valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
@@ -2579,7 +2689,8 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2589,9 +2700,10 @@
valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
// Data is empty, base should be reset.
- EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(5, curInterval.base.long_value);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2638,12 +2750,14 @@
// Key 1 should be reset since in not present in the most pull.
EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
auto iterator = valueProducer->mCurrentSlicedBucket.begin();
- EXPECT_EQ(true, iterator->second[0].hasBase);
- EXPECT_EQ(2, iterator->second[0].base.long_value);
+ auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
+ EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
iterator++;
- EXPECT_EQ(false, iterator->second[0].hasBase);
- EXPECT_EQ(1, iterator->second[0].base.long_value);
+ baseInfoIter++;
+ EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2715,8 +2829,9 @@
valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(true, curInterval.hasBase);
- EXPECT_EQ(5, curInterval.base.long_value);
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
@@ -2827,6 +2942,7 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(2, curInterval.value.long_value);
@@ -2918,8 +3034,7 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
- true /* include recent buckets */, true,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
FAST, &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
@@ -2970,9 +3085,8 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucket4StartTimeNs,
- false /* include recent buckets */, true,
- FAST, &strSet, &output);
+ valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+ &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
// Previous bucket is part of the report.
@@ -3023,8 +3137,7 @@
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
- true /* include recent buckets */, true,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
NO_TIME_CONSTRAINTS, &strSet, &output);
StatsLogReport report = outputStreamToProto(&output);
@@ -3058,15 +3171,15 @@
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}))
// condition becomes false
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 50, 20));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
return true;
}));
sp<ValueMetricProducer> valueProducer =
@@ -3079,11 +3192,11 @@
EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
EXPECT_EQ(20, curInterval.value.long_value);
-
// Now the alarm is delivered. Condition is off though.
vector<shared_ptr<LogEvent>> allData;
allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
@@ -3091,7 +3204,8 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3104,8 +3218,8 @@
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}));
sp<ValueMetricProducer> valueProducer =
@@ -3122,7 +3236,8 @@
assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
ValueMetricProducer::Interval curInterval =
valueProducer->mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
}
@@ -3153,8 +3268,8 @@
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
- data->push_back(ValueMetricProducerTestHelper::createEvent(
- bucketStartTimeNs + 30, 10));
+ data->push_back(
+ ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
return true;
}))
.WillOnce(Return(false));
@@ -3768,6 +3883,725 @@
EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
}
+/*
+ * Test metric with a simple sliced state
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedState) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write("field1");
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+ event->write("field1");
+ event->write(5);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to OFF.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(9);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+ event->write("field1");
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(30);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after screen state change kStateUnknown->ON.
+ auto screenEvent = CreateScreenStateChangedEvent(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(5, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change ON->OFF.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 10);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON}
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change OFF->ON.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ bucketStartTimeNs + 15);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(21, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, OFF}
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(12, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, ON}
+ it++;
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+ it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(3, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+}
+
+/*
+ * Test metric with sliced state with map
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write("field1");
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to ON.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+ event->write("field1");
+ event->write(5);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to VR.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+ event->write("field1");
+ event->write(9);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Screen state change to OFF.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+ event->write("field1");
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+ event->write("field1");
+ event->write(30);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ const StateMap& stateMap = CreateScreenStateOnOffMap();
+ const StateMap_StateGroup screenOnGroup = stateMap.group(0);
+ const StateMap_StateGroup screenOffGroup = stateMap.group(1);
+
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ for (auto group : stateMap.group()) {
+ for (auto value : group.value()) {
+ stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
+ }
+ }
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, {}}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after screen state change kStateUnknown->ON.
+ auto screenEvent = CreateScreenStateChangedEvent(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(5, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change ON->VR (also ON).
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+ bucketStartTimeNs + 10);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON GROUP}
+ EXPECT_EQ(screenOnGroup.group_id(),
+ it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Bucket status after screen state change VR->OFF.
+ screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+ bucketStartTimeNs + 15);
+ StateManager::getInstance().onLogEvent(*screenEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(21, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{}, ON GROUP}
+ EXPECT_EQ(screenOnGroup.group_id(),
+ it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(16, it->second[0].value.long_value);
+ // Value for dimension, state key {{}, kStateUnknown}
+ it++;
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(3, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+ EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+ EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
+}
+
+/*
+ * Test metric that slices by state with a primary field and has dimensions
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+ // Set up ValueMetricProducer.
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ MetricStateLink* stateLink = metric.add_state_link();
+ stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+ auto fieldsInWhat = stateLink->mutable_fields_in_what();
+ *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
+ auto fieldsInState = stateLink->mutable_fields_in_state();
+ *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // ValueMetricProducer initialized.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(2 /* uid */);
+ event->write(7);
+ event->init();
+ data->push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(1 /* uid */);
+ event->write(3);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from kStateUnknown -> Foreground
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+ event->write(1 /* uid */);
+ event->write(6);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+ event->write(2 /* uid */);
+ event->write(8);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 2 process state change from kStateUnknown -> Background
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+ event->write(2 /* uid */);
+ event->write(9);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+ event->write(1 /* uid */);
+ event->write(12);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from Foreground -> Background
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ event->write(1 /* uid */);
+ event->write(13);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+ event->write(2 /* uid */);
+ event->write(11);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Uid 1 process state change from Background -> Foreground
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+ event->write(1 /* uid */);
+ event->write(17);
+ event->init();
+ data->push_back(event);
+
+ // This event should be skipped.
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+ event->write(2 /* uid */);
+ event->write(15);
+ event->init();
+ data->push_back(event);
+ return true;
+ }))
+ // Dump report pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+ event->write(2 /* uid */);
+ event->write(20);
+ event->init();
+ data->push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+ event->write(1 /* uid */);
+ event->write(21);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithState(
+ pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
+
+ // Set up StateManager and check that StateTrackers are initialized.
+ StateManager::getInstance().clear();
+ StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
+ EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+ EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+ // Bucket status after metric initialized.
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(3, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{uid 1}, kStateUnknown}
+ // TODO(tsaichristine): test equality of state values key
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(7, itBase->second[0].base.long_value);
+ // Value for dimension, state key {{uid 2}, kStateUnknown}
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
+ auto uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(6, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}.
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(7, itBase->second[0].base.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 2 process state change kStateUnknown -> Background.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ // Base for dimension key {uid 1}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(6, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}.
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Base for dimension key {uid 2}
+ it++;
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(9, itBase->second[0].base.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(2, it->second[0].value.long_value);
+
+ // Pull at end of first bucket.
+ vector<shared_ptr<LogEvent>> allData;
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write(1 /* uid */);
+ event->write(10);
+ event->init();
+ allData.push_back(event);
+
+ event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+ event->write(2 /* uid */);
+ event->write(15);
+ event->init();
+ allData.push_back(event);
+
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ // Buckets flushed after end of first bucket.
+ // None of the buckets should have a value.
+ EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ // Value for key {uid 2, BACKGROUND}.
+ EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+ EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(10, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}
+ EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+ // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Value for key {uid 2, kStateUnknown}
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change from Foreground -> Background.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+ EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}.
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ // Value for key {uid 2, BACKGROUND}.
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(13, itBase->second[0].base.long_value);
+ // Value for key {uid 1, kStateUnknown}
+ EXPECT_EQ(false, it->second[0].hasValue);
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+ // Value for key {uid 2, kStateUnknown}
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Bucket status after uid 1 process state change Background->Foreground.
+ uidProcessEvent = CreateUidProcessStateChangedEvent(
+ 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+ StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+ EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+ // Base for dimension key {uid 2}
+ it = valueProducer->mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(true, itBase->second[0].hasBase);
+ EXPECT_EQ(15, itBase->second[0].base.long_value);
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ it++;
+ EXPECT_EQ(false, it->second[0].hasValue);
+
+ // Base for dimension key {uid 1}
+ it++;
+ EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+ itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+ EXPECT_EQ(17, itBase->second[0].base.long_value);
+ // Value for key {uid 1, BACKGROUND}
+ EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(4, it->second[0].value.long_value);
+ // Value for key {uid 1, FOREGROUND}
+ it++;
+ EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+ EXPECT_EQ(true, it->second[0].hasValue);
+ EXPECT_EQ(3, it->second[0].value.long_value);
+
+ // Start dump report and check output.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(5, report.value_metrics().data_size());
+
+ auto data = report.value_metrics().data(0);
+ EXPECT_EQ(1, data.bucket_info_size());
+ EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+ data.slice_by_state(0).value());
+
+ data = report.value_metrics().data(1);
+ EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(2);
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+ data.slice_by_state(0).value());
+ EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+ EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
+
+ data = report.value_metrics().data(3);
+ EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+ EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
+
+ data = report.value_metrics().data(4);
+ EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+ EXPECT_TRUE(data.slice_by_state(0).has_value());
+ EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+ data.slice_by_state(0).value());
+ EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+ EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
+ EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index 395167b..26a3733 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -146,6 +146,7 @@
TEST(StateManagerTest, TestStateManagerGetInstance) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager& mgr = StateManager::getInstance();
+ mgr.clear();
mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(1, mgr.getStateTrackersCount());
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 010c194..9bdfeeb 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -30,6 +30,9 @@
using android::util::ProtoReader;
using google::protobuf::RepeatedPtrField;
+const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
+const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
+
// Converts a ProtoOutputStream to a StatsLogReport proto.
StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 652669c..4d0acb3 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -14142,7 +14142,6 @@
HSPLandroid/telephony/ServiceState;->copyFrom(Landroid/telephony/ServiceState;)V
HSPLandroid/telephony/ServiceState;->describeContents()I
HSPLandroid/telephony/ServiceState;->equals(Ljava/lang/Object;)Z
-HSPLandroid/telephony/ServiceState;->fillInNotifierBundle(Landroid/os/Bundle;)V
HSPLandroid/telephony/ServiceState;->getCdmaDefaultRoamingIndicator()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconIndex()I
HSPLandroid/telephony/ServiceState;->getCdmaEriIconMode()I
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 08f8734..a4f6f57 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3659,7 +3659,7 @@
r.activity, Looper.myLooper());
}
r.activity.onGetDirectActions(cancellationSignal, (actions) -> {
- Preconditions.checkNotNull(actions);
+ Objects.requireNonNull(actions);
Preconditions.checkCollectionElementsNotNull(actions, "actions");
if (!actions.isEmpty()) {
final int actionCount = actions.size();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 86a5c76..b5ac37b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -51,6 +51,7 @@
import android.util.ArraySet;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
+import android.util.Pools;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
@@ -1159,8 +1160,6 @@
})
private @interface ShouldCollectNoteOp {}
- // Warning: If an permission is added here it also has to be added to
- // com.android.packageinstaller.permission.utils.EventLogger
private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
// RUNTIME PERMISSIONS
// Contacts
@@ -2045,7 +2044,7 @@
* transaction. Not set if this thread is currently not executing a two way binder transaction.
*
* @see #startNotedAppOpsCollection
- * @see #markAppOpNoted
+ * @see #getNotedOpCollectionMode
*/
private static final ThreadLocal<Integer> sBinderThreadCallingUid = new ThreadLocal<>();
@@ -2053,7 +2052,8 @@
* If a thread is currently executing a two-way binder transaction, this stores the op-codes of
* the app-ops that were noted during this transaction.
*
- * @see #markAppOpNoted
+ * @see #getNotedOpCollectionMode
+ * @see #collectNotedOpSync
*/
private static final ThreadLocal<ArrayMap<String, long[]>> sAppOpsNotedInThisBinderTransaction =
new ThreadLocal<>();
@@ -2341,15 +2341,31 @@
*/
@TestApi
@SystemApi
- @Immutable
- @DataClass(genHiddenConstructor = true)
+ // @DataClass(genHiddenConstructor = true, genHiddenCopyConstructor = true)
+ // genHiddenCopyConstructor does not work for @hide @SystemApi classes
public static final class OpEventProxyInfo implements Parcelable {
/** UID of the proxy app that noted the op */
- private final @IntRange(from = 0) int mUid;
+ private @IntRange(from = 0) int mUid;
/** Package of the proxy that noted the op */
- private final @Nullable String mPackageName;
+ private @Nullable String mPackageName;
/** ID of the feature of the proxy that noted the op */
- private final @Nullable String mFeatureId;
+ private @Nullable String mFeatureId;
+
+ /**
+ * Reinit existing object with new state.
+ *
+ * @param uid UID of the proxy app that noted the op
+ * @param packageName Package of the proxy that noted the op
+ * @param featureId ID of the feature of the proxy that noted the op
+ *
+ * @hide
+ */
+ public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName,
+ @Nullable String featureId) {
+ mUid = Preconditions.checkArgumentNonnegative(uid);
+ mPackageName = packageName;
+ mFeatureId = featureId;
+ }
@@ -2393,6 +2409,18 @@
}
/**
+ * Copy constructor
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public OpEventProxyInfo(@NonNull OpEventProxyInfo orig) {
+ mUid = orig.mUid;
+ mPackageName = orig.mPackageName;
+ mFeatureId = orig.mFeatureId;
+ }
+
+ /**
* UID of the proxy app that noted the op
*/
@DataClass.Generated.Member
@@ -2471,14 +2499,15 @@
}
};
+ /*
@DataClass.Generated(
- time = 1576194071700L,
+ time = 1576814974615L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L) int mUid\nprivate final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ inputSignatures = "private @android.annotation.IntRange(from=0L) int mUid\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.Nullable java.lang.String mFeatureId\npublic void reinit(int,java.lang.String,java.lang.String)\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genHiddenCopyConstructor=true)")
@Deprecated
private void __metadata() {}
-
+ */
//@formatter:on
// End of generated code
@@ -2490,15 +2519,48 @@
*
* @hide
*/
- @Immutable
//@DataClass codegen verifier is broken
public static final class NoteOpEvent implements Parcelable {
/** Time of noteOp event */
- public final @IntRange(from = 0) long noteTime;
+ private @IntRange(from = 0) long mNoteTime;
/** The duration of this event (in case this is a startOp event, -1 otherwise). */
- public final @IntRange(from = -1) long duration;
+ private @IntRange(from = -1) long mDuration;
/** Proxy information of the noteOp event */
- public final @Nullable OpEventProxyInfo proxy;
+ private @Nullable OpEventProxyInfo mProxy;
+
+ /**
+ * Reinit existing object with new state.
+ *
+ * @param noteTime Time of noteOp event
+ * @param duration The duration of this event (in case this is a startOp event,
+ * -1 otherwise).
+ * @param proxy Proxy information of the noteOp event
+ * @param proxyPool The pool to release previous {@link OpEventProxyInfo} to
+ */
+ public void reinit(@IntRange(from = 0) long noteTime,
+ @IntRange(from = -1) long duration,
+ @Nullable OpEventProxyInfo proxy,
+ @NonNull Pools.Pool<OpEventProxyInfo> proxyPool) {
+ mNoteTime = Preconditions.checkArgumentNonnegative(noteTime);
+ mDuration = Preconditions.checkArgumentInRange(duration, -1L, Long.MAX_VALUE,
+ "duration");
+
+ if (mProxy != null) {
+ proxyPool.release(mProxy);
+ }
+ mProxy = proxy;
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @hide
+ */
+ public NoteOpEvent(@NonNull NoteOpEvent original) {
+ this(original.mNoteTime, original.mDuration,
+ original.mProxy != null ? new OpEventProxyInfo(original.mProxy) : null);
+ }
+
// Code below generated by codegen v1.0.14.
@@ -2529,19 +2591,43 @@
@IntRange(from = 0) long noteTime,
@IntRange(from = -1) long duration,
@Nullable OpEventProxyInfo proxy) {
- this.noteTime = noteTime;
+ this.mNoteTime = noteTime;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, noteTime,
+ IntRange.class, null, mNoteTime,
"from", 0);
- this.duration = duration;
+ this.mDuration = duration;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, duration,
+ IntRange.class, null, mDuration,
"from", -1);
- this.proxy = proxy;
+ this.mProxy = proxy;
// onConstructed(); // You can define this method to get a callback
}
+ /**
+ * Time of noteOp event
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 0) long getNoteTime() {
+ return mNoteTime;
+ }
+
+ /**
+ * The duration of this event (in case this is a startOp event, -1 otherwise).
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = -1) long getDuration() {
+ return mDuration;
+ }
+
+ /**
+ * Proxy information of the noteOp event
+ */
+ @DataClass.Generated.Member
+ public @Nullable OpEventProxyInfo getProxy() {
+ return mProxy;
+ }
+
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -2549,11 +2635,11 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (proxy != null) flg |= 0x4;
+ if (mProxy != null) flg |= 0x4;
dest.writeByte(flg);
- dest.writeLong(noteTime);
- dest.writeLong(duration);
- if (proxy != null) dest.writeTypedObject(proxy, flags);
+ dest.writeLong(mNoteTime);
+ dest.writeLong(mDuration);
+ if (mProxy != null) dest.writeTypedObject(mProxy, flags);
}
@Override
@@ -2568,20 +2654,19 @@
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
- long _noteTime = in.readLong();
- long _duration = in.readLong();
- OpEventProxyInfo _proxy = (flg & 0x4) == 0 ? null : (OpEventProxyInfo) in.readTypedObject(
- OpEventProxyInfo.CREATOR);
+ long noteTime = in.readLong();
+ long duration = in.readLong();
+ OpEventProxyInfo proxy = (flg & 0x4) == 0 ? null : (OpEventProxyInfo) in.readTypedObject(OpEventProxyInfo.CREATOR);
- this.noteTime = _noteTime;
+ this.mNoteTime = noteTime;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, noteTime,
+ IntRange.class, null, mNoteTime,
"from", 0);
- this.duration = _duration;
+ this.mDuration = duration;
com.android.internal.util.AnnotationValidations.validate(
- IntRange.class, null, duration,
+ IntRange.class, null, mDuration,
"from", -1);
- this.proxy = _proxy;
+ this.mProxy = proxy;
// onConstructed(); // You can define this method to get a callback
}
@@ -2602,10 +2687,10 @@
/*
@DataClass.Generated(
- time = 1574809856220L,
+ time = 1576811792274L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "public final @android.annotation.IntRange(from=0L) long noteTime\npublic final @android.annotation.IntRange(from=-1) long duration\npublic final @android.annotation.Nullable android.app.NoteOpEventProxyInfo proxy\nclass NoteOpEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+ inputSignatures = "private @android.annotation.IntRange(from=0L) long mNoteTime\nprivate @android.annotation.IntRange(from=-1) long mDuration\nprivate @android.annotation.Nullable android.app.OpEventProxyInfo mProxy\npublic void reinit(long,long,android.app.OpEventProxyInfo,android.util.Pools.Pool<android.app.OpEventProxyInfo>)\npublic @java.lang.Override java.lang.Object clone()\nclass NoteOpEvent extends java.lang.Object implements [android.os.Parcelable, java.lang.Cloneable]\n@com.android.internal.util.DataClass")
@Deprecated
private void __metadata() {}
*/
@@ -2751,7 +2836,7 @@
return -1;
}
- return lastEvent.noteTime;
+ return lastEvent.getNoteTime();
}
/**
@@ -2847,7 +2932,7 @@
return -1;
}
- return lastEvent.noteTime;
+ return lastEvent.getNoteTime();
}
/**
@@ -2922,7 +3007,7 @@
return -1;
}
- return lastEvent.duration;
+ return lastEvent.getDuration();
}
/**
@@ -3000,7 +3085,7 @@
return null;
}
- return lastEvent.proxy;
+ return lastEvent.getProxy();
}
private static class LongSparseArrayParceling implements
@@ -3304,7 +3389,7 @@
toUidState, flags);
if (lastAccessEvent == null || (lastFeatureAccessEvent != null
- && lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
+ && lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
lastAccessEvent = lastFeatureAccessEvent;
}
}
@@ -3335,7 +3420,7 @@
return -1;
}
- return lastEvent.noteTime;
+ return lastEvent.getNoteTime();
}
/**
@@ -3418,7 +3503,7 @@
toUidState, flags);
if (lastAccessEvent == null || (lastFeatureAccessEvent != null
- && lastFeatureAccessEvent.noteTime > lastAccessEvent.noteTime)) {
+ && lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
lastAccessEvent = lastFeatureAccessEvent;
}
}
@@ -3449,7 +3534,7 @@
return -1;
}
- return lastEvent.noteTime;
+ return lastEvent.getNoteTime();
}
/**
@@ -3544,7 +3629,7 @@
return -1;
}
- return lastEvent.duration;
+ return lastEvent.getDuration();
}
/**
@@ -3674,7 +3759,7 @@
return null;
}
- return lastEvent.proxy;
+ return lastEvent.getProxy();
}
@@ -5517,8 +5602,8 @@
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
@NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) {
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
@@ -5556,8 +5641,8 @@
@RequiresPermission(Manifest.permission.MANAGE_APPOPS)
public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request,
@Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) {
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
@@ -6236,9 +6321,23 @@
public int noteOpNoThrow(int op, int uid, @Nullable String packageName,
@Nullable String featureId, @Nullable String message) {
try {
- int mode = mService.noteOperation(op, uid, packageName, featureId);
+ int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
+ if (collectionMode == COLLECT_ASYNC) {
+ if (message == null) {
+ // Set stack trace as default message
+ message = getFormattedStackTrace();
+ }
+ }
+
+ int mode = mService.noteOperation(op, uid, packageName, featureId,
+ collectionMode == COLLECT_ASYNC, message);
+
if (mode == MODE_ALLOWED) {
- markAppOpNoted(uid, packageName, op, featureId, message);
+ if (collectionMode == COLLECT_SELF) {
+ collectNotedOpForSelf(op, featureId);
+ } else if (collectionMode == COLLECT_SYNC) {
+ collectNotedOpSync(op, featureId);
+ }
}
return mode;
@@ -6382,14 +6481,27 @@
int myUid = Process.myUid();
try {
+ int collectionMode = getNotedOpCollectionMode(proxiedUid, proxiedPackageName, op);
+ if (collectionMode == COLLECT_ASYNC) {
+ if (message == null) {
+ // Set stack trace as default message
+ message = getFormattedStackTrace();
+ }
+ }
+
int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
proxiedFeatureId, myUid, mContext.getOpPackageName(),
- mContext.getFeatureId());
- if (mode == MODE_ALLOWED
- // Only collect app-ops when the proxy is trusted
- && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1, myUid)
- == PackageManager.PERMISSION_GRANTED) {
- markAppOpNoted(proxiedUid, proxiedPackageName, op, proxiedFeatureId, message);
+ mContext.getFeatureId(), collectionMode == COLLECT_ASYNC, message);
+
+ if (mode == MODE_ALLOWED) {
+ if (collectionMode == COLLECT_SELF) {
+ collectNotedOpForSelf(op, proxiedFeatureId);
+ } else if (collectionMode == COLLECT_SYNC
+ // Only collect app-ops when the proxy is trusted
+ && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
+ myUid) == PackageManager.PERMISSION_GRANTED) {
+ collectNotedOpSync(op, proxiedFeatureId);
+ }
}
return mode;
@@ -6679,10 +6791,23 @@
public int startOpNoThrow(int op, int uid, @NonNull String packageName,
boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
try {
+ int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
+ if (collectionMode == COLLECT_ASYNC) {
+ if (message == null) {
+ // Set stack trace as default message
+ message = getFormattedStackTrace();
+ }
+ }
+
int mode = mService.startOperation(getClientId(), op, uid, packageName,
- featureId, startIfModeDefault);
+ featureId, startIfModeDefault, collectionMode == COLLECT_ASYNC, message);
+
if (mode == MODE_ALLOWED) {
- markAppOpNoted(uid, packageName, op, featureId, message);
+ if (collectionMode == COLLECT_SELF) {
+ collectNotedOpForSelf(op, featureId);
+ } else if (collectionMode == COLLECT_SYNC) {
+ collectNotedOpSync(op, featureId);
+ }
}
return mode;
@@ -6846,85 +6971,106 @@
}
/**
- * Mark an app-op as noted
+ * Collect a noted op for the current process.
+ *
+ * @param op The noted op
+ * @param featureId The feature the op is noted for
*/
- private void markAppOpNoted(int uid, @Nullable String packageName, int code,
- @Nullable String featureId, @Nullable String message) {
+ private void collectNotedOpForSelf(int op, @Nullable String featureId) {
+ synchronized (sLock) {
+ if (sNotedAppOpsCollector != null) {
+ sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(op, featureId));
+ }
+ }
+ }
+
+ /**
+ * Collect a noted op when inside of a two-way binder call.
+ *
+ * <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
+ *
+ * @param op The noted op
+ * @param featureId The feature the op is noted for
+ */
+ private void collectNotedOpSync(int op, @Nullable String featureId) {
+ // If this is inside of a two-way binder call:
+ // We are inside of a two-way binder call. Delivered to caller via
+ // {@link #prefixParcelWithAppOpsIfNeeded}
+ ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
+ if (appOpsNoted == null) {
+ appOpsNoted = new ArrayMap<>(1);
+ sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
+ }
+
+ long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
+ if (appOpsNotedForFeature == null) {
+ appOpsNotedForFeature = new long[2];
+ appOpsNoted.put(featureId, appOpsNotedForFeature);
+ }
+
+ if (op < 64) {
+ appOpsNotedForFeature[0] |= 1L << op;
+ } else {
+ appOpsNotedForFeature[1] |= 1L << (op - 64);
+ }
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ DONT_COLLECT,
+ COLLECT_SELF,
+ COLLECT_SYNC,
+ COLLECT_ASYNC
+ })
+ private @interface NotedOpCollectionMode {}
+ private static final int DONT_COLLECT = 0;
+ private static final int COLLECT_SELF = 1;
+ private static final int COLLECT_SYNC = 2;
+ private static final int COLLECT_ASYNC = 3;
+
+ /**
+ * Mark an app-op as noted.
+ */
+ private @NotedOpCollectionMode int getNotedOpCollectionMode(int uid,
+ @Nullable String packageName, int op) {
if (packageName == null) {
packageName = "android";
}
// check it the appops needs to be collected and cache result
- if (sAppOpsToNote[code] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
+ if (sAppOpsToNote[op] == SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED) {
boolean shouldCollectNotes;
try {
- shouldCollectNotes = mService.shouldCollectNotes(code);
+ shouldCollectNotes = mService.shouldCollectNotes(op);
} catch (RemoteException e) {
- return;
+ return DONT_COLLECT;
}
if (shouldCollectNotes) {
- sAppOpsToNote[code] = SHOULD_COLLECT_NOTE_OP;
+ sAppOpsToNote[op] = SHOULD_COLLECT_NOTE_OP;
} else {
- sAppOpsToNote[code] = SHOULD_NOT_COLLECT_NOTE_OP;
+ sAppOpsToNote[op] = SHOULD_NOT_COLLECT_NOTE_OP;
}
}
- if (sAppOpsToNote[code] != SHOULD_COLLECT_NOTE_OP) {
- return;
+ if (sAppOpsToNote[op] != SHOULD_COLLECT_NOTE_OP) {
+ return DONT_COLLECT;
+ }
+
+ synchronized (sLock) {
+ if (uid == Process.myUid()
+ && packageName.equals(ActivityThread.currentOpPackageName())) {
+ return COLLECT_SELF;
+ }
}
Integer binderUid = sBinderThreadCallingUid.get();
- synchronized (sLock) {
- if (sNotedAppOpsCollector != null && uid == Process.myUid() && packageName.equals(
- ActivityThread.currentOpPackageName())) {
- // This app is noting an app-op for itself. Deliver immediately.
- sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code, featureId));
-
- return;
- }
- }
-
if (binderUid != null && binderUid == uid) {
- // If this is inside of a two-way binder call: Delivered to caller via
- // {@link #prefixParcelWithAppOpsIfNeeded}
- // We are inside of a two-way binder call. Delivered to caller via
- // {@link #prefixParcelWithAppOpsIfNeeded}
- ArrayMap<String, long[]> appOpsNoted = sAppOpsNotedInThisBinderTransaction.get();
- if (appOpsNoted == null) {
- appOpsNoted = new ArrayMap<>(1);
- sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
- }
-
- long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
- if (appOpsNotedForFeature == null) {
- appOpsNotedForFeature = new long[2];
- appOpsNoted.put(featureId, appOpsNotedForFeature);
- }
-
- if (code < 64) {
- appOpsNotedForFeature[0] |= 1L << code;
- } else {
- appOpsNotedForFeature[1] |= 1L << (code - 64);
- }
+ return COLLECT_SYNC;
} else {
- // Cannot deliver the note synchronous: Hence send it to the system server to
- // notify the noted process.
- if (message == null) {
- // Default message is a stack trace
- message = getFormattedStackTrace();
- }
-
- long token = Binder.clearCallingIdentity();
- try {
- mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code,
- featureId, message);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ return COLLECT_ASYNC;
}
}
@@ -7062,7 +7208,7 @@
private final IAppOpsAsyncNotedCallback mAsyncCb = new IAppOpsAsyncNotedCallback.Stub() {
@Override
public void opNoted(AsyncNotedAppOp op) {
- Preconditions.checkNotNull(op);
+ Objects.requireNonNull(op);
getAsyncNotedExecutor().execute(() -> onAsyncNoted(op));
}
@@ -7331,7 +7477,8 @@
final long key = makeKey(uidState, flag);
NoteOpEvent event = events.get(key);
- if (lastEvent == null || event != null && event.noteTime > lastEvent.noteTime) {
+ if (lastEvent == null
+ || event != null && event.getNoteTime() > lastEvent.getNoteTime()) {
lastEvent = event;
}
}
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index bd7ef2a..099037c 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.util.SparseIntArray;
+import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction;
/**
@@ -63,12 +64,16 @@
* @param uid The UID for which to note.
* @param packageName The package for which to note. {@code null} for system package.
* @param featureId Id of the feature in the package
+ * @param shouldCollectAsyncNotedOp If an {@link AsyncNotedAppOp} should be collected
+ * @param message The message in the async noted op
* @param superImpl The super implementation.
* @return The app op note result.
*/
int noteOperation(int code, int uid, @Nullable String packageName,
- @Nullable String featureId,
- @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl);
+ @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+ @Nullable String message,
+ @NonNull HexFunction<Integer, Integer, String, String, Boolean, String, Integer>
+ superImpl);
}
/**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7f26565..1c6a561 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -100,7 +100,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.UserIcons;
import dalvik.system.VMRuntime;
@@ -2149,7 +2148,7 @@
} else if (vol.isPrimaryPhysical()) {
volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
} else {
- volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
+ volumeUuid = Objects.requireNonNull(vol.fsUuid);
}
return mPM.movePackage(packageName, volumeUuid);
@@ -2259,7 +2258,7 @@
} else if (vol.isPrimaryPhysical()) {
volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
} else {
- volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
+ volumeUuid = Objects.requireNonNull(vol.fsUuid);
}
return mPM.movePrimaryStorage(volumeUuid);
@@ -2661,8 +2660,8 @@
/** @hide */
@Override
public KeySet getKeySetByAlias(String packageName, String alias) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(alias);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(alias);
try {
return mPM.getKeySetByAlias(packageName, alias);
} catch (RemoteException e) {
@@ -2673,7 +2672,7 @@
/** @hide */
@Override
public KeySet getSigningKeySet(String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
try {
return mPM.getSigningKeySet(packageName);
} catch (RemoteException e) {
@@ -2684,8 +2683,8 @@
/** @hide */
@Override
public boolean isSignedBy(String packageName, KeySet ks) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(ks);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(ks);
try {
return mPM.isPackageSignedByKeySet(packageName, ks);
} catch (RemoteException e) {
@@ -2696,8 +2695,8 @@
/** @hide */
@Override
public boolean isSignedByExactly(String packageName, KeySet ks) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(ks);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(ks);
try {
return mPM.isPackageSignedByKeySetExactly(packageName, ks);
} catch (RemoteException e) {
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 0e1f921..c3ef3ad 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -45,12 +45,6 @@
/** Uid that noted the op */
private final @IntRange(from = 0) int mNotingUid;
- /**
- * Package that noted the op. {@code null} if the package name that noted the op could be not
- * be determined (e.g. when the op is noted from native code).
- */
- private final @Nullable String mNotingPackageName;
-
/** {@link android.content.Context#createFeatureContext Feature} in the app */
private final @Nullable String mFeatureId;
@@ -69,7 +63,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.14.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -89,9 +83,6 @@
* Op that was noted
* @param notingUid
* Uid that noted the op
- * @param notingPackageName
- * Package that noted the op. {@code null} if the package name that noted the op could be not
- * be determined (e.g. when the op is noted from native code).
* @param featureId
* {@link android.content.Context#createFeatureContext Feature} in the app
* @param message
@@ -104,7 +95,6 @@
public AsyncNotedAppOp(
@IntRange(from = 0, to = AppOpsManager._NUM_OP - 1) int opCode,
@IntRange(from = 0) int notingUid,
- @Nullable String notingPackageName,
@Nullable String featureId,
@NonNull String message,
@IntRange(from = 0) long time) {
@@ -117,7 +107,6 @@
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
"from", 0);
- this.mNotingPackageName = notingPackageName;
this.mFeatureId = featureId;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
@@ -139,15 +128,6 @@
}
/**
- * Package that noted the op. {@code null} if the package name that noted the op could be not
- * be determined (e.g. when the op is noted from native code).
- */
- @DataClass.Generated.Member
- public @Nullable String getNotingPackageName() {
- return mNotingPackageName;
- }
-
- /**
* {@link android.content.Context#createFeatureContext Feature} in the app
*/
@DataClass.Generated.Member
@@ -186,7 +166,6 @@
return true
&& mOpCode == that.mOpCode
&& mNotingUid == that.mNotingUid
- && java.util.Objects.equals(mNotingPackageName, that.mNotingPackageName)
&& java.util.Objects.equals(mFeatureId, that.mFeatureId)
&& java.util.Objects.equals(mMessage, that.mMessage)
&& mTime == that.mTime;
@@ -201,7 +180,6 @@
int _hash = 1;
_hash = 31 * _hash + mOpCode;
_hash = 31 * _hash + mNotingUid;
- _hash = 31 * _hash + java.util.Objects.hashCode(mNotingPackageName);
_hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
_hash = 31 * _hash + java.util.Objects.hashCode(mMessage);
_hash = 31 * _hash + Long.hashCode(mTime);
@@ -215,12 +193,10 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mNotingPackageName != null) flg |= 0x4;
- if (mFeatureId != null) flg |= 0x8;
+ if (mFeatureId != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeInt(mOpCode);
dest.writeInt(mNotingUid);
- if (mNotingPackageName != null) dest.writeString(mNotingPackageName);
if (mFeatureId != null) dest.writeString(mFeatureId);
dest.writeString(mMessage);
dest.writeLong(mTime);
@@ -240,8 +216,7 @@
byte flg = in.readByte();
int opCode = in.readInt();
int notingUid = in.readInt();
- String notingPackageName = (flg & 0x4) == 0 ? null : in.readString();
- String featureId = (flg & 0x8) == 0 ? null : in.readString();
+ String featureId = (flg & 0x4) == 0 ? null : in.readString();
String message = in.readString();
long time = in.readLong();
@@ -254,7 +229,6 @@
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
"from", 0);
- this.mNotingPackageName = notingPackageName;
this.mFeatureId = featureId;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
@@ -282,11 +256,15 @@
};
@DataClass.Generated(
- time = 1571327470155L,
- codegenVersion = "1.0.9",
+ time = 1576864422226L,
+ codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/core/java/android/app/AuthenticationRequiredException.java b/core/java/android/app/AuthenticationRequiredException.java
index 0d87336..847d2c4 100644
--- a/core/java/android/app/AuthenticationRequiredException.java
+++ b/core/java/android/app/AuthenticationRequiredException.java
@@ -21,7 +21,7 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* Specialization of {@link SecurityException} that is thrown when authentication is needed from the
@@ -60,7 +60,7 @@
*/
public AuthenticationRequiredException(Throwable cause, PendingIntent userAction) {
super(cause.getMessage());
- mUserAction = Preconditions.checkNotNull(userAction);
+ mUserAction = Objects.requireNonNull(userAction);
}
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bd87fcd..cd84310 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2794,7 +2794,7 @@
public ApplicationContentResolver(Context context, ActivityThread mainThread) {
super(context);
- mMainThread = Preconditions.checkNotNull(mainThread);
+ mMainThread = Objects.requireNonNull(mainThread);
}
@Override
diff --git a/core/java/android/app/DirectAction.java b/core/java/android/app/DirectAction.java
index ef3627b..0268f7c 100644
--- a/core/java/android/app/DirectAction.java
+++ b/core/java/android/app/DirectAction.java
@@ -172,7 +172,7 @@
* current application state.
*/
public Builder(@NonNull String id) {
- Preconditions.checkNotNull(id);
+ Objects.requireNonNull(id);
mId = id;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 453c600..775b1d1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -46,7 +46,7 @@
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.sysprop.ProductProperties;
+import android.sysprop.VndkProperties;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
@@ -785,13 +785,12 @@
// Similar to vendor apks, we should add /product/lib for apks from product partition
// when product apps are marked as unbundled. We cannot use the same way from vendor
// to check if lib path exists because there is possibility that /product/lib would not
- // exist from legacy device while product apks are bundled. To make this clear, new
- // property ("ro.product.apps.unbundled") is defined which should be true only when
- // product apks are unbundled.
+ // exist from legacy device while product apks are bundled. To make this clear, we use
+ // "ro.product.vndk.version" property. If the property is defined, we regard all product
+ // apks as unbundled.
if (mApplicationInfo.getCodePath() != null
- && mApplicationInfo.isProduct() && ProductProperties.unbundled_apps().orElse(false)
- // TODO(b/128557860): Change target SDK version when version code R is available.
- && getTargetSdkVersion() == Build.VERSION_CODES.CUR_DEVELOPMENT) {
+ && mApplicationInfo.isProduct()
+ && VndkProperties.product_vndk_version().isPresent()) {
isBundledApp = false;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 31c73b9..ca3d0d7 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -198,6 +198,7 @@
import com.android.internal.util.Preconditions;
import java.util.Map;
+import java.util.Objects;
/**
* Manages all of the system services that can be returned by {@link Context#getSystemService}.
@@ -1429,8 +1430,8 @@
@NonNull StaticServiceProducerWithBinder<TServiceClass> serviceProducer) {
ensureInitializing("registerStaticService");
Preconditions.checkStringNotEmpty(serviceName);
- Preconditions.checkNotNull(serviceWrapperClass);
- Preconditions.checkNotNull(serviceProducer);
+ Objects.requireNonNull(serviceWrapperClass);
+ Objects.requireNonNull(serviceProducer);
registerService(serviceName, serviceWrapperClass,
new StaticServiceFetcher<TServiceClass>() {
@@ -1453,8 +1454,8 @@
@NonNull StaticServiceProducerWithoutBinder<TServiceClass> serviceProducer) {
ensureInitializing("registerStaticService");
Preconditions.checkStringNotEmpty(serviceName);
- Preconditions.checkNotNull(serviceWrapperClass);
- Preconditions.checkNotNull(serviceProducer);
+ Objects.requireNonNull(serviceWrapperClass);
+ Objects.requireNonNull(serviceProducer);
registerService(serviceName, serviceWrapperClass,
new StaticServiceFetcher<TServiceClass>() {
@@ -1486,8 +1487,8 @@
@NonNull ContextAwareServiceProducerWithBinder<TServiceClass> serviceProducer) {
ensureInitializing("registerContextAwareService");
Preconditions.checkStringNotEmpty(serviceName);
- Preconditions.checkNotNull(serviceWrapperClass);
- Preconditions.checkNotNull(serviceProducer);
+ Objects.requireNonNull(serviceWrapperClass);
+ Objects.requireNonNull(serviceProducer);
registerService(serviceName, serviceWrapperClass,
new CachedServiceFetcher<TServiceClass>() {
@@ -1514,8 +1515,8 @@
@NonNull ContextAwareServiceProducerWithoutBinder<TServiceClass> serviceProducer) {
ensureInitializing("registerContextAwareService");
Preconditions.checkStringNotEmpty(serviceName);
- Preconditions.checkNotNull(serviceWrapperClass);
- Preconditions.checkNotNull(serviceProducer);
+ Objects.requireNonNull(serviceWrapperClass);
+ Objects.requireNonNull(serviceProducer);
registerService(serviceName, serviceWrapperClass,
new CachedServiceFetcher<TServiceClass>() {
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index b37120f..c262ec2 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -44,6 +44,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -1129,8 +1130,8 @@
*/
public boolean registerOnDestroyedCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Runnable callback) {
- Preconditions.checkNotNull(executor);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
if (isDestroyed()) {
Log.w(TAG, "Cannot interact with a destroyed voice interactor");
return false;
@@ -1146,7 +1147,7 @@
* @return whether the callback was unregistered.
*/
public boolean unregisterOnDestroyedCallback(@NonNull Runnable callback) {
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
if (isDestroyed()) {
Log.w(TAG, "Cannot interact with a destroyed voice interactor");
return false;
diff --git a/core/java/android/app/admin/DevicePolicyEventLogger.java b/core/java/android/app/admin/DevicePolicyEventLogger.java
index 95a7973..4c0e176 100644
--- a/core/java/android/app/admin/DevicePolicyEventLogger.java
+++ b/core/java/android/app/admin/DevicePolicyEventLogger.java
@@ -25,6 +25,7 @@
import com.android.internal.util.Preconditions;
import java.util.Arrays;
+import java.util.Objects;
/**
* A wrapper for logging managed device events using {@link StatsLog}.
@@ -136,7 +137,7 @@
* in that order.
*/
public DevicePolicyEventLogger setStrings(String value, String[] values) {
- Preconditions.checkNotNull(values, "values parameter cannot be null");
+ Objects.requireNonNull(values, "values parameter cannot be null");
mStringArrayValue = new String[values.length + 1];
mStringArrayValue[0] = value;
System.arraycopy(values, 0, mStringArrayValue, 1, values.length);
@@ -150,7 +151,7 @@
* and <code>values</code>, in that order.
*/
public DevicePolicyEventLogger setStrings(String value1, String value2, String[] values) {
- Preconditions.checkNotNull(values, "values parameter cannot be null");
+ Objects.requireNonNull(values, "values parameter cannot be null");
mStringArrayValue = new String[values.length + 2];
mStringArrayValue[0] = value1;
mStringArrayValue[1] = value2;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index acdf919..8daaaaa 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -115,6 +115,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -4263,7 +4264,7 @@
* {@link #WIPE_SILENTLY} is set.
*/
public void wipeData(int flags, @NonNull CharSequence reason) {
- Preconditions.checkNotNull(reason, "reason string is null");
+ Objects.requireNonNull(reason, "reason string is null");
Preconditions.checkStringNotEmpty(reason, "reason string is empty");
Preconditions.checkArgument((flags & WIPE_SILENTLY) == 0, "WIPE_SILENTLY cannot be set");
wipeDataInternal(flags, reason.toString());
@@ -10430,8 +10431,8 @@
@NonNull String packageName, @NonNull @CallbackExecutor Executor executor,
@NonNull OnClearApplicationUserDataListener listener) {
throwIfParentInstance("clearAppData");
- Preconditions.checkNotNull(executor);
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
try {
mService.clearApplicationUserData(admin, packageName,
new IPackageDataObserver.Stub() {
@@ -10881,7 +10882,7 @@
@WorkerThread public @PrivateDnsModeErrorCodes int setGlobalPrivateDnsModeSpecifiedHost(
@NonNull ComponentName admin, @NonNull String privateDnsHost) {
throwIfParentInstance("setGlobalPrivateDnsModeSpecifiedHost");
- Preconditions.checkNotNull(privateDnsHost, "dns resolver is null");
+ Objects.requireNonNull(privateDnsHost, "dns resolver is null");
if (mService == null) {
return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 80c5b17..22d8c87 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -41,6 +41,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* <p>This API automatically creates assist data from the platform's
@@ -1889,7 +1890,7 @@
@Override
public void setTextIdEntry(@NonNull String entryName) {
- mNode.mTextIdEntry = Preconditions.checkNotNull(entryName);
+ mNode.mTextIdEntry = Objects.requireNonNull(entryName);
}
@Override
@@ -1899,7 +1900,7 @@
@Override
public void setHintIdEntry(@NonNull String entryName) {
- mNode.mHintIdEntry = Preconditions.checkNotNull(entryName);
+ mNode.mHintIdEntry = Objects.requireNonNull(entryName);
}
@Override
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index cb5b7e7..ca22721 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -20,7 +20,7 @@
import android.annotation.TestApi;
import android.content.Context;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* Class that provides methods to create prediction clients.
@@ -37,7 +37,7 @@
* @hide
*/
public AppPredictionManager(Context context) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
}
/**
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 6f21490..14e32b83 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -25,7 +25,7 @@
import android.os.Parcelable;
import android.os.UserHandle;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
/**
* A representation of a launchable target.
@@ -55,9 +55,9 @@
mId = id;
mShortcutInfo = null;
- mPackageName = Preconditions.checkNotNull(packageName);
+ mPackageName = Objects.requireNonNull(packageName);
mClassName = className;
- mUser = Preconditions.checkNotNull(user);
+ mUser = Objects.requireNonNull(user);
mRank = 0;
}
@@ -69,7 +69,7 @@
public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo,
@Nullable String className) {
mId = id;
- mShortcutInfo = Preconditions.checkNotNull(shortcutInfo);
+ mShortcutInfo = Objects.requireNonNull(shortcutInfo);
mPackageName = mShortcutInfo.getPackage();
mUser = mShortcutInfo.getUserHandle();
@@ -224,9 +224,9 @@
@TestApi
public Builder(@NonNull AppTargetId id, @NonNull String packageName,
@NonNull UserHandle user) {
- mId = Preconditions.checkNotNull(id);
- mPackageName = Preconditions.checkNotNull(packageName);
- mUser = Preconditions.checkNotNull(user);
+ mId = Objects.requireNonNull(id);
+ mPackageName = Objects.requireNonNull(packageName);
+ mUser = Objects.requireNonNull(user);
}
/**
@@ -237,8 +237,8 @@
@SystemApi
@TestApi
public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
- mId = Preconditions.checkNotNull(id);
- mShortcutInfo = Preconditions.checkNotNull(info);
+ mId = Objects.requireNonNull(id);
+ mShortcutInfo = Objects.requireNonNull(info);
mPackageName = info.getPackage();
mUser = info.getUserHandle();
}
@@ -253,8 +253,8 @@
if (mPackageName != null) {
throw new IllegalArgumentException("Target is already set");
}
- mPackageName = Preconditions.checkNotNull(packageName);
- mUser = Preconditions.checkNotNull(user);
+ mPackageName = Objects.requireNonNull(packageName);
+ mUser = Objects.requireNonNull(user);
return this;
}
@@ -266,7 +266,7 @@
@Deprecated
public Builder setTarget(@NonNull ShortcutInfo info) {
setTarget(info.getPackage(), info.getUserHandle());
- mShortcutInfo = Preconditions.checkNotNull(info);
+ mShortcutInfo = Objects.requireNonNull(info);
return this;
}
@@ -275,7 +275,7 @@
*/
@NonNull
public Builder setClassName(@NonNull String className) {
- mClassName = Preconditions.checkNotNull(className);
+ mClassName = Objects.requireNonNull(className);
return this;
}
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index a7319f6..823fdd2 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -28,7 +28,6 @@
import android.os.Parcelable;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -428,7 +427,7 @@
* @see SliceItem#getSubType()
*/
public Builder addSubSlice(@NonNull Slice slice, @Nullable @SliceSubtype String subType) {
- Preconditions.checkNotNull(slice);
+ Objects.requireNonNull(slice);
mItems.add(new SliceItem(slice, SliceItem.FORMAT_SLICE, subType,
slice.getHints().toArray(new String[slice.getHints().size()])));
return this;
@@ -441,8 +440,8 @@
*/
public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s,
@Nullable @SliceSubtype String subType) {
- Preconditions.checkNotNull(action);
- Preconditions.checkNotNull(s);
+ Objects.requireNonNull(action);
+ Objects.requireNonNull(s);
List<String> hints = s.getHints();
s.mSpec = null;
mItems.add(new SliceItem(action, s, SliceItem.FORMAT_ACTION, subType, hints.toArray(
@@ -468,7 +467,7 @@
*/
public Builder addIcon(Icon icon, @Nullable @SliceSubtype String subType,
@SliceHint List<String> hints) {
- Preconditions.checkNotNull(icon);
+ Objects.requireNonNull(icon);
mItems.add(new SliceItem(icon, SliceItem.FORMAT_IMAGE, subType, hints));
return this;
}
@@ -481,7 +480,7 @@
public Slice.Builder addRemoteInput(RemoteInput remoteInput,
@Nullable @SliceSubtype String subType,
@SliceHint List<String> hints) {
- Preconditions.checkNotNull(remoteInput);
+ Objects.requireNonNull(remoteInput);
mItems.add(new SliceItem(remoteInput, SliceItem.FORMAT_REMOTE_INPUT,
subType, hints));
return this;
@@ -529,7 +528,7 @@
*/
public Slice.Builder addBundle(Bundle bundle, @Nullable @SliceSubtype String subType,
@SliceHint List<String> hints) {
- Preconditions.checkNotNull(bundle);
+ Objects.requireNonNull(bundle);
mItems.add(new SliceItem(bundle, SliceItem.FORMAT_BUNDLE, subType,
hints));
return this;
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 90ecce2..4da1acb 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -51,6 +51,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -241,7 +242,7 @@
* @see Slice
*/
public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull Set<SliceSpec> supportedSpecs) {
- Preconditions.checkNotNull(uri, "uri");
+ Objects.requireNonNull(uri, "uri");
ContentResolver resolver = mContext.getContentResolver();
try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
if (provider == null) {
@@ -336,7 +337,7 @@
}
private Uri resolveStatic(@NonNull Intent intent, ContentResolver resolver) {
- Preconditions.checkNotNull(intent, "intent");
+ Objects.requireNonNull(intent, "intent");
Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
|| intent.getData() != null,
"Slice intent must be explicit %s", intent);
@@ -371,7 +372,7 @@
*/
public @Nullable Slice bindSlice(@NonNull Intent intent,
@NonNull Set<SliceSpec> supportedSpecs) {
- Preconditions.checkNotNull(intent, "intent");
+ Objects.requireNonNull(intent, "intent");
Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
|| intent.getData() != null,
"Slice intent must be explicit %s", intent);
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 7412970..4346d97 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -16,8 +16,6 @@
package android.app.usage;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -42,6 +40,8 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.util.Objects;
+
/**
* Provides access to network usage history and statistics. Usage data is collected in
* discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -418,7 +418,7 @@
/** @hide */
public void registerUsageCallback(NetworkTemplate template, int networkType,
long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
- checkNotNull(callback, "UsageCallback cannot be null");
+ Objects.requireNonNull(callback, "UsageCallback cannot be null");
final Looper looper;
if (handler == null) {
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index eecf092..1ef1563 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -63,8 +63,8 @@
/** {@hide} */
public StorageStatsManager(Context context, IStorageStatsManager service) {
- mContext = Preconditions.checkNotNull(context);
- mService = Preconditions.checkNotNull(service);
+ mContext = Objects.requireNonNull(context);
+ mService = Objects.requireNonNull(service);
}
/** {@hide} */
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 83eaa72..38498bc 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -472,63 +472,6 @@
}
/**
- * Get the volume of the device.
- *
- * <p> The volume is between -128 dB (mute) to 0 dB.
- *
- * @return volume of the hearing aid device.
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH)
- public int getVolume() {
- if (VDBG) {
- log("getVolume()");
- }
- final IBluetoothHearingAid service = getService();
- try {
- if (service != null && isEnabled()) {
- return service.getVolume();
- }
- if (service == null) Log.w(TAG, "Proxy not attached to service");
- return 0;
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return 0;
- }
- }
-
- /**
- * Tells remote device to adjust volume. Uses the following values:
- * <ul>
- * <li>{@link AudioManager#ADJUST_LOWER}</li>
- * <li>{@link AudioManager#ADJUST_RAISE}</li>
- * <li>{@link AudioManager#ADJUST_MUTE}</li>
- * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
- * </ul>
- *
- * @param direction One of the supported adjust values.
- * @hide
- */
- @RequiresPermission(Manifest.permission.BLUETOOTH)
- public void adjustVolume(int direction) {
- if (DBG) log("adjustVolume(" + direction + ")");
-
- final IBluetoothHearingAid service = getService();
- try {
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- return;
- }
-
- if (!isEnabled()) return;
-
- service.adjustVolume(direction);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- }
- }
-
- /**
* Tells remote device to set an absolute volume.
*
* @param volume Absolute volume to be set on remote
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 47edf2e..32803ab 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -202,6 +202,7 @@
public static final String TAG_OVERLAY = "overlay";
public static final String TAG_PACKAGE = "package";
public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
+ public static final String TAG_FEATURE = "feature";
public static final String TAG_PERMISSION = "permission";
public static final String TAG_PERMISSION_GROUP = "permission-group";
public static final String TAG_PERMISSION_TREE = "permission-tree";
diff --git a/core/java/android/content/pm/VersionedPackage.java b/core/java/android/content/pm/VersionedPackage.java
index 3e22eb2..21df7ec 100644
--- a/core/java/android/content/pm/VersionedPackage.java
+++ b/core/java/android/content/pm/VersionedPackage.java
@@ -96,6 +96,20 @@
}
@Override
+ public boolean equals(Object o) {
+ return o instanceof VersionedPackage
+ && ((VersionedPackage) o).mPackageName.equals(mPackageName)
+ && ((VersionedPackage) o).mVersionCode == mVersionCode;
+ }
+
+ @Override
+ public int hashCode() {
+ // Roll our own hash function without using Objects#hash which incurs the overhead
+ // of autoboxing.
+ return 31 * mPackageName.hashCode() + Long.hashCode(mVersionCode);
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/content/pm/parsing/AndroidPackage.java b/core/java/android/content/pm/parsing/AndroidPackage.java
index 0562dff..990c835 100644
--- a/core/java/android/content/pm/parsing/AndroidPackage.java
+++ b/core/java/android/content/pm/parsing/AndroidPackage.java
@@ -27,6 +27,7 @@
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
+import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
@@ -245,6 +246,9 @@
List<ParsedInstrumentation> getInstrumentations();
@Nullable
+ List<ParsedFeature> getFeatures();
+
+ @Nullable
List<ParsedPermissionGroup> getPermissionGroups();
@Nullable
diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java
index 3f22967..a001ada 100644
--- a/core/java/android/content/pm/parsing/ApkParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkParseUtils.java
@@ -793,6 +793,10 @@
parseResult = parseKeySets(parseInput, parsingPackage, res, parser);
success = parseResult.isSuccess();
break;
+ case PackageParser.TAG_FEATURE:
+ parseResult = parseFeature(parseInput, parsingPackage, res, parser);
+ success = parseResult.isSuccess();
+ break;
case PackageParser.TAG_PERMISSION_GROUP:
parseResult = parsePermissionGroup(parseInput, parsingPackage, res,
parser);
@@ -880,6 +884,13 @@
);
}
+ if (!ComponentParseUtils.ParsedFeature.isCombinationValid(parsingPackage.getFeatures())) {
+ return parseInput.error(
+ INSTALL_PARSE_FAILED_BAD_MANIFEST,
+ "Combination <feature> tags are not valid"
+ );
+ }
+
convertNewPermissions(parsingPackage);
convertSplitPermissions(parsingPackage);
@@ -1260,6 +1271,31 @@
return parseInput.success(parsingPackage);
}
+ private static ParseResult parseFeature(
+ ParseInput parseInput,
+ ParsingPackage parsingPackage,
+ Resources res,
+ XmlResourceParser parser
+ ) throws IOException, XmlPullParserException {
+ // TODO(b/135203078): Remove, replace with ParseResult
+ String[] outError = new String[1];
+
+ ComponentParseUtils.ParsedFeature parsedFeature =
+ ComponentParseUtils.parseFeature(res, parser, outError);
+
+ if (parsedFeature == null || outError[0] != null) {
+ return parseInput.error(
+ PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ outError[0]
+ );
+ }
+
+ parsingPackage.addFeature(parsedFeature);
+
+ return parseInput.success(parsingPackage);
+ }
+
+
private static ParseResult parsePermissionGroup(
ParseInput parseInput,
ParsingPackage parsingPackage,
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
index fc210b2..7b24d3d 100644
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java
@@ -24,6 +24,9 @@
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
import android.content.ComponentName;
@@ -47,6 +50,7 @@
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -54,6 +58,7 @@
import android.view.Gravity;
import com.android.internal.R;
+import com.android.internal.util.DataClass;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -62,6 +67,7 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -931,6 +937,186 @@
};
}
+ /**
+ * A {@link android.R.styleable#AndroidManifestFeature <feature>} tag parsed from the
+ * manifest.
+ */
+ // @DataClass verifier is broken, hence comment out for now
+ public static class ParsedFeature implements Parcelable {
+ /** Maximum length of featureId */
+ public static final int MAX_FEATURE_ID_LEN = 50;
+
+ /** Maximum amount of features per package */
+ private static final int MAX_NUM_FEATURES = 1000;
+
+ /** Id of the feature */
+ public final @NonNull String id;
+
+ /** User visible label fo the feature */
+ public final @StringRes int label;
+
+ /** Ids of previously declared features this feature inherits from */
+ public final @NonNull List<String> inheritFrom;
+
+ /**
+ * @return Is this set of features a valid combination for a single package?
+ */
+ public static boolean isCombinationValid(@Nullable List<ParsedFeature> features) {
+ if (features == null) {
+ return true;
+ }
+
+ ArraySet<String> featureIds = new ArraySet<>(features.size());
+ ArraySet<String> inheritFromFeatureIds = new ArraySet<>();
+
+ int numFeatures = features.size();
+ if (numFeatures > MAX_NUM_FEATURES) {
+ return false;
+ }
+
+ for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+ boolean wasAdded = featureIds.add(features.get(featureNum).id);
+ if (!wasAdded) {
+ // feature id is not unique
+ return false;
+ }
+ }
+
+ for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+ ParsedFeature feature = features.get(featureNum);
+
+ int numInheritFrom = feature.inheritFrom.size();
+ for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
+ String inheritFrom = feature.inheritFrom.get(inheritFromNum);
+
+ if (featureIds.contains(inheritFrom)) {
+ // Cannot inherit from a feature that is still defined
+ return false;
+ }
+
+ boolean wasAdded = inheritFromFeatureIds.add(inheritFrom);
+ if (!wasAdded) {
+ // inheritFrom is not unique
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new ParsedFeature.
+ *
+ * @param id
+ * Id of the feature
+ * @param label
+ * User visible label fo the feature (if defined as resource)
+ * @param inheritFrom
+ * Ids of previously declared features this feature inherits from
+ */
+ @DataClass.Generated.Member
+ public ParsedFeature(
+ @NonNull String id,
+ @StringRes int label,
+ @NonNull List<String> inheritFrom) {
+ this.id = id;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, id);
+ this.label = label;
+ com.android.internal.util.AnnotationValidations.validate(
+ StringRes.class, null, label);
+ this.inheritFrom = inheritFrom;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, inheritFrom);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(id);
+ dest.writeInt(label);
+ dest.writeStringList(inheritFrom);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected ParsedFeature(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String _id = in.readString();
+ int _label = in.readInt();
+ List<String> _inheritFrom = new ArrayList<>();
+ in.readStringList(_inheritFrom);
+
+ this.id = _id;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, id);
+ this.label = _label;
+ com.android.internal.util.AnnotationValidations.validate(
+ StringRes.class, null, label);
+ this.inheritFrom = _inheritFrom;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, inheritFrom);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<ParsedFeature> CREATOR
+ = new Parcelable.Creator<ParsedFeature>() {
+ @Override
+ public ParsedFeature[] newArray(int size) {
+ return new ParsedFeature[size];
+ }
+
+ @Override
+ public ParsedFeature createFromParcel(@NonNull Parcel in) {
+ return new ParsedFeature(in);
+ }
+ };
+
+ /*@DataClass.Generated(
+ time = 1576783172965L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java",
+ inputSignatures = "public final @android.annotation.NonNull java.lang.String id\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static boolean isCombinationValid(java.util.List<android.content.pm.parsing.ParsedFeature>)\nclass ParsedFeature extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+ */
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
public static class ParsedPermission extends ParsedComponent<ParsedIntentInfo> {
public String backgroundPermission;
@@ -2566,6 +2752,85 @@
return result;
}
+ public static ParsedFeature parseFeature(
+ Resources res,
+ XmlResourceParser parser,
+ String[] outError
+ ) throws IOException, XmlPullParserException {
+ String featureId;
+ int label;
+ List<String> inheritFrom = null;
+
+ TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeature);
+ if (sa == null) {
+ outError[0] = "<feature> could not be parsed";
+ return null;
+ }
+
+ try {
+ featureId = sa.getNonConfigurationString(R.styleable.AndroidManifestFeature_featureId,
+ 0);
+ if (featureId == null) {
+ outError[0] = "<featureId> does not specify android:featureId";
+ return null;
+ }
+ if (featureId.length() > ParsedFeature.MAX_FEATURE_ID_LEN) {
+ outError[0] = "<featureId> is too long. Max length is "
+ + ParsedFeature.MAX_FEATURE_ID_LEN;
+ return null;
+ }
+
+ label = sa.getResourceId(R.styleable.AndroidManifestFeature_label, 0);
+ if (label == Resources.ID_NULL) {
+ outError[0] = "<featureId> does not specify android:label";
+ return null;
+ }
+ } finally {
+ sa.recycle();
+ }
+
+ int type;
+ final int innerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("inherit-from")) {
+ sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeatureInheritFrom);
+ if (sa == null) {
+ outError[0] = "<inherit-from> could not be parsed";
+ return null;
+ }
+
+ try {
+ String inheritFromId = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestFeatureInheritFrom_featureId,0);
+
+ if (inheritFrom == null) {
+ inheritFrom = new ArrayList<>();
+ }
+ inheritFrom.add(inheritFromId);
+ } finally {
+ sa.recycle();
+ }
+ } else {
+ outError[0] = "Bad element under <feature>: " + tagName;
+ return null;
+ }
+ }
+
+ if (inheritFrom == null) {
+ inheritFrom = Collections.emptyList();
+ } else {
+ ((ArrayList) inheritFrom).trimToSize();
+ }
+
+ return new ParsedFeature(featureId, label, inheritFrom);
+ }
+
public static ParsedPermission parsePermission(
ParsingPackage parsingPackage,
Resources res,
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
index 18dee23..8677fce 100644
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ b/core/java/android/content/pm/parsing/PackageImpl.java
@@ -36,6 +36,7 @@
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
+import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
@@ -175,6 +176,9 @@
private ArrayList<ComponentParseUtils.ParsedProvider> providers;
@Nullable
+ private ArrayList<ComponentParseUtils.ParsedFeature> features;
+
+ @Nullable
private ArrayList<ComponentParseUtils.ParsedPermission> permissions;
@Nullable
@@ -580,6 +584,12 @@
return permissions;
}
+ @Nullable
+ @Override
+ public List<ParsedFeature> getFeatures() {
+ return features;
+ }
+
@Override
public String getCpuAbiOverride() {
return cpuAbiOverride;
@@ -792,6 +802,12 @@
}
@Override
+ public PackageImpl addFeature(ParsedFeature feature) {
+ this.features = ArrayUtils.add(this.features, feature);
+ return this;
+ }
+
+ @Override
public PackageImpl addPermission(ParsedPermission permission) {
this.permissions = ArrayUtils.add(this.permissions, permission);
return this;
@@ -3021,6 +3037,7 @@
dest.writeTypedList(this.receivers);
dest.writeTypedList(this.services);
dest.writeTypedList(this.providers);
+ dest.writeTypedList(this.features);
dest.writeTypedList(this.permissions);
dest.writeTypedList(this.permissionGroups);
dest.writeTypedList(this.instrumentations);
@@ -3173,6 +3190,7 @@
this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR);
this.services = in.createTypedArrayList(ParsedService.CREATOR);
this.providers = in.createTypedArrayList(ParsedProvider.CREATOR);
+ this.features = in.createTypedArrayList(ParsedFeature.CREATOR);
this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR);
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 47dac55..411c749 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageParser;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
+import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
@@ -64,6 +65,8 @@
ParsingPackage addOverlayable(String overlayableName, String actorName);
+ ParsingPackage addFeature(ParsedFeature permission);
+
ParsingPackage addPermission(ParsedPermission permission);
ParsingPackage addPermissionGroup(ParsedPermissionGroup permissionGroup);
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index c89796d..6378db0 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -88,6 +89,11 @@
private final SparseLongArray mCeSnapshotInodes;
/**
+ * The userdata policy to execute when a rollback for this package is committed.
+ */
+ private final int mRollbackDataPolicy;
+
+ /**
* Returns the name of the package to roll back from.
*/
@NonNull
@@ -148,6 +154,11 @@
}
/** @hide */
+ public @PackageManager.RollbackDataPolicy int getRollbackDataPolicy() {
+ return mRollbackDataPolicy;
+ }
+
+ /** @hide */
public IntArray getSnapshottedUsers() {
return mSnapshottedUsers;
}
@@ -181,11 +192,23 @@
@NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
boolean isApex, @NonNull IntArray snapshottedUsers,
@NonNull SparseLongArray ceSnapshotInodes) {
+ this(packageRolledBackFrom, packageRolledBackTo, pendingBackups, pendingRestores, isApex,
+ snapshottedUsers, ceSnapshotInodes, PackageManager.RollbackDataPolicy.RESTORE);
+ }
+
+ /** @hide */
+ public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
+ VersionedPackage packageRolledBackTo,
+ @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
+ boolean isApex, @NonNull IntArray snapshottedUsers,
+ @NonNull SparseLongArray ceSnapshotInodes,
+ @PackageManager.RollbackDataPolicy int rollbackDataPolicy) {
this.mVersionRolledBackFrom = packageRolledBackFrom;
this.mVersionRolledBackTo = packageRolledBackTo;
this.mPendingBackups = pendingBackups;
this.mPendingRestores = pendingRestores;
this.mIsApex = isApex;
+ this.mRollbackDataPolicy = rollbackDataPolicy;
this.mSnapshottedUsers = snapshottedUsers;
this.mCeSnapshotInodes = ceSnapshotInodes;
}
@@ -198,6 +221,7 @@
this.mPendingBackups = null;
this.mSnapshottedUsers = null;
this.mCeSnapshotInodes = null;
+ this.mRollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
}
@Override
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 7e1506f..4c114fd 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -90,19 +90,19 @@
* @hide
*/
@SystemApi
- int EMPTY_SET = 0x0;
+ int EMPTY_SET = 0x0000;
/**
* Placeholder for the theoretical strongest biometric security tier.
* @hide
*/
- int BIOMETRIC_MAX_STRENGTH = 0x001;
+ int BIOMETRIC_MAX_STRENGTH = 0x0001;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
* requirements for <strong>Strong</strong>, as defined by the Android CDD.
*/
- int BIOMETRIC_STRONG = 0x00F;
+ int BIOMETRIC_STRONG = 0x000F;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -111,7 +111,7 @@
* <p>Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that
* <code>BIOMETRIC_STRONG | BIOMETRIC_WEAK == BIOMETRIC_WEAK</code>.
*/
- int BIOMETRIC_WEAK = 0x0FF;
+ int BIOMETRIC_WEAK = 0x00FF;
/**
* Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -121,7 +121,7 @@
* @hide
*/
@SystemApi
- int BIOMETRIC_CONVENIENCE = 0xFFF;
+ int BIOMETRIC_CONVENIENCE = 0x0FFF;
/**
* Placeholder for the theoretical weakest biometric security tier.
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index c3ebe43..6f90db4 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -240,6 +240,11 @@
*
* <p>This value is looked up the first time, and cached subsequently.</p>
*
+ * <p>This function may be called without cacheTag() if this is not a vendor key.
+ * If this is a vendor key, cacheTag() must be called first before getTag() can
+ * be called. Otherwise, mVendorId could be default (Long.MAX_VALUE) and vendor
+ * tag lookup could fail.</p>
+ *
* @return The tag numeric value corresponding to the string
*/
@UnsupportedAppUsage
@@ -252,6 +257,27 @@
}
/**
+ * Whether this key's tag is cached.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public final boolean hasTag() {
+ return mHasTag;
+ }
+
+ /**
+ * Cache this key's tag.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public final void cacheTag(int tag) {
+ mHasTag = true;
+ mTag = tag;
+ }
+
+ /**
* Get the raw class backing the type {@code T} for this key.
*
* <p>The distinction is only important if {@code T} is a generic, e.g.
@@ -523,7 +549,13 @@
}
private <T> T getBase(Key<T> key) {
- int tag = nativeGetTagFromKeyLocal(key.getName());
+ int tag;
+ if (key.hasTag()) {
+ tag = key.getTag();
+ } else {
+ tag = nativeGetTagFromKeyLocal(key.getName());
+ key.cacheTag(tag);
+ }
byte[] values = readValues(tag);
if (values == null) {
// If the key returns null, use the fallback key if exists.
@@ -1451,7 +1483,13 @@
}
private <T> void setBase(Key<T> key, T value) {
- int tag = nativeGetTagFromKeyLocal(key.getName());
+ int tag;
+ if (key.hasTag()) {
+ tag = key.getTag();
+ } else {
+ tag = nativeGetTagFromKeyLocal(key.getName());
+ key.cacheTag(tag);
+ }
if (value == null) {
// Erase the entry
writeValues(tag, /*src*/null);
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a45f703..fe4f860 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -722,15 +722,6 @@
}
/**
- * Returns whether inline suggestions are enabled on this service.
- *
- * TODO(b/137800469): check XML for value.
- */
- private boolean isInlineSuggestionsEnabled() {
- return true;
- }
-
- /**
* Sends an {@link InlineSuggestionsRequest} obtained from
* {@link #onCreateInlineSuggestionsRequest()} to the current Autofill Session through
* {@link IInlineSuggestionsRequestCallback#onInlineSuggestionsRequest}.
@@ -763,23 +754,14 @@
private void handleOnCreateInlineSuggestionsRequest(@NonNull ComponentName componentName,
@NonNull AutofillId autofillId, @NonNull IInlineSuggestionsRequestCallback callback) {
- mInlineSuggestionsRequestInfo = new InlineSuggestionsRequestInfo(componentName, autofillId,
- callback);
-
- if (!isInlineSuggestionsEnabled()) {
- try {
- callback.onInlineSuggestionsUnsupported();
- } catch (RemoteException e) {
- Log.w(TAG, "handleMakeInlineSuggestionsRequest() RemoteException:" + e);
- }
- return;
- }
-
if (!mInputStarted) {
Log.w(TAG, "onStartInput() not called yet");
return;
}
+ mInlineSuggestionsRequestInfo = new InlineSuggestionsRequestInfo(componentName, autofillId,
+ callback);
+
makeInlineSuggestionsRequest();
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 1c4ef382..3d44944 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2590,4 +2590,12 @@
* @hide
*/
public static native long getIonMappedSizeKb();
+
+ /**
+ * Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
+ * Note: caller needs config_gz read sepolicy permission
+ *
+ * @hide
+ */
+ public static native boolean isVmapStack();
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index a3215a4..2583292 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -318,8 +318,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
- Manifest.permission.PACKAGE_USAGE_STATS})
+ @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
public void startOneTimePermissionSession(@NonNull String packageName, long timeoutMillis,
@ActivityManager.RunningAppProcessInfo.Importance int importanceToResetTimer,
@ActivityManager.RunningAppProcessInfo.Importance int importanceToKeepSessionAlive) {
@@ -340,8 +339,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
- Manifest.permission.PACKAGE_USAGE_STATS})
+ @RequiresPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS)
public void stopOneTimePermissionSession(@NonNull String packageName) {
try {
mPermissionManager.stopOneTimePermissionSession(packageName,
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index fed3d7ba..c95e132 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3559,7 +3559,8 @@
* can manage DPC-owned APNs.
* @hide
*/
- public static final Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
+ @SystemApi
+ public static final @NonNull Uri DPC_URI = Uri.parse("content://telephony/carriers/dpc");
/**
* The {@code content://} style URL to be called from Telephony to query APNs.
@@ -3868,6 +3869,13 @@
public static final String USER_EDITABLE = "user_editable";
/**
+ * Integer value denoting an invalid APN id
+ * @hide
+ */
+ @SystemApi
+ public static final int INVALID_APN_ID = -1;
+
+ /**
* {@link #EDITED_STATUS APN edit status} indicates that this APN has not been edited or
* fails to edit.
* <p>Type: INTEGER </p>
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index b7ec281..fbc25a6 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -80,6 +80,8 @@
@Nullable
private final ArrayMap<String, Long> mCompatibilityPackages;
+ private final boolean mInlineSuggestionsEnabled;
+
public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
throws PackageManager.NameNotFoundException {
this(context, getServiceInfoOrThrow(comp, userHandle));
@@ -112,11 +114,13 @@
if (parser == null) {
mSettingsActivity = null;
mCompatibilityPackages = null;
+ mInlineSuggestionsEnabled = false;
return;
}
String settingsActivity = null;
ArrayMap<String, Long> compatibilityPackages = null;
+ boolean inlineSuggestionsEnabled = false; // false by default.
try {
final Resources resources = context.getPackageManager().getResourcesForApplication(
@@ -135,6 +139,8 @@
com.android.internal.R.styleable.AutofillService);
settingsActivity = afsAttributes.getString(
R.styleable.AutofillService_settingsActivity);
+ inlineSuggestionsEnabled = afsAttributes.getBoolean(
+ R.styleable.AutofillService_supportsInlineSuggestions, false);
} finally {
if (afsAttributes != null) {
afsAttributes.recycle();
@@ -150,6 +156,7 @@
mSettingsActivity = settingsActivity;
mCompatibilityPackages = compatibilityPackages;
+ mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
}
private ArrayMap<String, Long> parseCompatibilityPackages(XmlPullParser parser,
@@ -227,6 +234,10 @@
return mCompatibilityPackages;
}
+ public boolean isInlineSuggestionsEnabled() {
+ return mInlineSuggestionsEnabled;
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
@@ -235,6 +246,7 @@
builder.append(", settings:").append(mSettingsActivity);
builder.append(", hasCompatPckgs:").append(mCompatibilityPackages != null
&& !mCompatibilityPackages.isEmpty()).append("]");
+ builder.append(", inline suggestions enabled:").append(mInlineSuggestionsEnabled);
return builder.toString();
}
@@ -245,5 +257,7 @@
pw.print(prefix); pw.print("Component: "); pw.println(getServiceInfo().getComponentName());
pw.print(prefix); pw.print("Settings: "); pw.println(mSettingsActivity);
pw.print(prefix); pw.print("Compat packages: "); pw.println(mCompatibilityPackages);
+ pw.print(prefix); pw.print("Inline Suggestions Enabled: ");
+ pw.println(mInlineSuggestionsEnabled);
}
}
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 484eddc..6334d9d 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -38,6 +38,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.service.autofill.Dataset;
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.util.Log;
import android.util.Pair;
@@ -47,6 +48,7 @@
import android.view.autofill.AutofillValue;
import android.view.autofill.IAugmentedAutofillManagerClient;
import android.view.autofill.IAutofillWindowPresenter;
+import android.view.inputmethod.InlineSuggestionsRequest;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -106,10 +108,11 @@
@Override
public void onFillRequest(int sessionId, IBinder client, int taskId,
ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
- long requestTime, IFillCallback callback) {
+ long requestTime, @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
+ IFillCallback callback) {
mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
AugmentedAutofillService.this, sessionId, client, taskId, componentName,
- focusedId, focusedValue, requestTime, callback));
+ focusedId, focusedValue, requestTime, inlineSuggestionsRequest, callback));
}
@Override
@@ -212,6 +215,7 @@
private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
@NonNull ComponentName componentName, @NonNull AutofillId focusedId,
@Nullable AutofillValue focusedValue, long requestTime,
+ @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
@NonNull IFillCallback callback) {
if (mAutofillProxies == null) {
mAutofillProxies = new SparseArray<>();
@@ -236,9 +240,8 @@
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- // TODO(b/146453195): pass the inline suggestion request over.
- onFillRequest(new FillRequest(proxy, /* inlineSuggestionsRequest= */null),
- cancellationSignal, new FillController(proxy), new FillCallback(proxy));
+ onFillRequest(new FillRequest(proxy, inlineSuggestionsRequest), cancellationSignal,
+ new FillController(proxy), new FillCallback(proxy));
}
private void handleOnDestroyAllFillWindowsRequest() {
@@ -484,6 +487,14 @@
}
}
+ public void onInlineSuggestionsDataReady(@NonNull List<Dataset> inlineSuggestionsData) {
+ try {
+ mCallback.onSuccess(inlineSuggestionsData.toArray(new Dataset[]{}));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling back with the inline suggestions data: " + e);
+ }
+ }
+
// Used (mostly) for metrics.
public void report(@ReportEvent int event) {
if (sVerbose) Log.v(TAG, "report(): " + event);
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index 0251386..b767799 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -21,9 +21,12 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.service.autofill.Dataset;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.Log;
+import java.util.List;
+
/**
* Callback used to indicate at {@link FillRequest} has been fulfilled.
*
@@ -45,7 +48,7 @@
* Sets the response associated with the request.
*
* @param response response associated with the request, or {@code null} if the service
- * could not provide autofill for the request.
+ * could not provide autofill for the request.
*/
public void onSuccess(@Nullable FillResponse response) {
if (sDebug) Log.d(TAG, "onSuccess(): " + response);
@@ -55,6 +58,12 @@
return;
}
+ List<Dataset> inlineSuggestions = response.getInlineSuggestions();
+ if (inlineSuggestions != null && !inlineSuggestions.isEmpty()) {
+ mProxy.onInlineSuggestionsDataReady(inlineSuggestions);
+ return;
+ }
+
final FillWindow fillWindow = response.getFillWindow();
if (fillWindow != null) {
fillWindow.show();
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
index 103fc4d..4911348 100644
--- a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -22,6 +22,7 @@
import android.service.autofill.augmented.IFillCallback;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import android.view.inputmethod.InlineSuggestionsRequest;
import java.util.List;
@@ -35,7 +36,9 @@
void onDisconnected();
void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
in ComponentName activityComponent, in AutofillId focusedId,
- in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
+ in AutofillValue focusedValue, long requestTime,
+ in InlineSuggestionsRequest inlineSuggestionsRequest,
+ in IFillCallback callback);
void onDestroyAllFillWindowsRequest();
}
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 2fd51a1..eca8541 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -20,7 +20,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
import android.content.Intent;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -88,7 +87,7 @@
* {@link Control.StatelessBuilder}).
* @param controls
*/
- public void onLoad(@NonNull List<Control> controls) {
+ public final void onLoad(@NonNull List<Control> controls) {
Preconditions.checkNotNull(controls);
List<Control> list = new ArrayList<>();
for (Control control: controls) {
@@ -114,7 +113,7 @@
* their state.
* @param statefulControls
*/
- public void onRefreshState(@NonNull List<Control> statefulControls) {
+ public final void onRefreshState(@NonNull List<Control> statefulControls) {
Preconditions.checkNotNull(statefulControls);
try {
mCallback.onRefreshState(mToken, statefulControls);
@@ -128,7 +127,7 @@
* @param controlId
* @param response
*/
- public void onControlActionResponse(
+ public final void onControlActionResponse(
@NonNull String controlId, @ControlAction.ResponseResult int response) {
Preconditions.checkNotNull(controlId);
if (!ControlAction.isValidResponse(response)) {
@@ -172,7 +171,7 @@
public void onAction(String id, ControlAction action) {
ActionMessage msg = new ActionMessage(id, action);
- mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, msg).sendToTarget();
+ mHandler.obtainMessage(RequestHandler.MSG_ON_ACTION, msg).sendToTarget();
}
};
}
diff --git a/core/java/android/service/controls/templates/ThermostatTemplate.aidl b/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
similarity index 94%
rename from core/java/android/service/controls/templates/ThermostatTemplate.aidl
rename to core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
index 1fefda4..7994d26 100644
--- a/core/java/android/service/controls/templates/ThermostatTemplate.aidl
+++ b/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
@@ -16,4 +16,4 @@
package android.service.controls.templates;
-parcelable ThermostatTemplate;
\ No newline at end of file
+parcelable TemperatureControlTemplate;
\ No newline at end of file
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index 28a5c20..ff2f4ad 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -228,24 +228,6 @@
}
/**
- * Return the networkTypes array converted to a {@link TelephonyManager.NetworkTypeBitMask}
- * @hide
- */
- public long getNetworkTypesBitMask() {
- // calculate bitmask the first time and save for future calls
- if (networkTypesBitMask == 0) {
- if (networkTypes == null) {
- networkTypesBitMask = ~0;
- } else {
- for (int networkType : networkTypes) {
- networkTypesBitMask |= TelephonyManager.getBitMaskForNetworkType(networkType);
- }
- }
- }
- return networkTypesBitMask;
- }
-
- /**
* Return an iterator that will return all valid data usage cycles based on
* any recurrence rules. The iterator starts from the currently active cycle
* and walks backwards through time.
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 08e4eeb..5f74b2a 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -82,9 +82,6 @@
// Input event dispatching is paused.
public boolean paused;
- // Window layer.
- public int layer;
-
// Id of process and user that owns the window.
public int ownerPid;
public int ownerUid;
@@ -126,7 +123,6 @@
@Override
public String toString() {
return new StringBuilder(name != null ? name : "")
- .append(", layer=").append(layer)
.append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
.append(frameRight).append(",").append(frameBottom).append("]")
.append(", touchableRegion=").append(touchableRegion)
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index 64c8777..cfd624a 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -68,7 +68,7 @@
}
/**
- * Checks is this is a text value.
+ * Checks if this is a text value.
*
* <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.</p>
*/
@@ -89,7 +89,7 @@
}
/**
- * Checks is this is a toggle value.
+ * Checks if this is a toggle value.
*
* <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.</p>
*/
@@ -110,7 +110,7 @@
}
/**
- * Checks is this is a list value.
+ * Checks if this is a list value.
*
* <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.</p>
*/
@@ -131,7 +131,7 @@
}
/**
- * Checks is this is a date value.
+ * Checks if this is a date value.
*
* <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.</p>
*/
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 34005ac..2864485 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -58,6 +58,7 @@
* @attr ref android.R.styleable#InputMethod_settingsActivity
* @attr ref android.R.styleable#InputMethod_isDefault
* @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
+ * @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -111,6 +112,11 @@
private final boolean mSupportsSwitchingToNextInputMethod;
/**
+ * The flag whether this IME supports inline suggestions.
+ */
+ private final boolean mInlineSuggestionsEnabled;
+
+ /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -152,6 +158,7 @@
mId = computeId(service);
boolean isAuxIme = true;
boolean supportsSwitchingToNextInputMethod = false; // false as default
+ boolean inlineSuggestionsEnabled = false; // false as default
mForceDefault = false;
PackageManager pm = context.getPackageManager();
@@ -193,6 +200,8 @@
supportsSwitchingToNextInputMethod = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
false);
+ inlineSuggestionsEnabled = sa.getBoolean(
+ com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
sa.recycle();
final int depth = parser.getDepth();
@@ -263,6 +272,7 @@
mIsDefaultResId = isDefaultResId;
mIsAuxIme = isAuxIme;
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
+ mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mIsVrOnly = isVrOnly;
}
@@ -272,6 +282,7 @@
mIsDefaultResId = source.readInt();
mIsAuxIme = source.readInt() == 1;
mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
+ mInlineSuggestionsEnabled = source.readInt() == 1;
mIsVrOnly = source.readBoolean();
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
@@ -286,7 +297,7 @@
this(buildDummyResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* isVrOnly */);
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */);
}
/**
@@ -297,7 +308,8 @@
String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- true /* supportsSwitchingToNextInputMethod */, false /* isVrOnly */);
+ true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
+ false /* isVrOnly */);
}
/**
@@ -307,6 +319,18 @@
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
+ this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
+ supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly);
+ }
+
+ /**
+ * Temporary API for creating a built-in input method for test.
+ * @hide
+ */
+ public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
+ List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
+ boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
+ boolean isVrOnly) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -316,6 +340,7 @@
mSubtypes = new InputMethodSubtypeArray(subtypes);
mForceDefault = forceDefault;
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
+ mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mIsVrOnly = isVrOnly;
}
@@ -467,7 +492,8 @@
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
+ " mIsVrOnly=" + mIsVrOnly
- + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
+ + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
+ + " mInlineSuggestionsEnabled=" + mInlineSuggestionsEnabled);
pw.println(prefix + "mIsDefaultResId=0x"
+ Integer.toHexString(mIsDefaultResId));
pw.println(prefix + "Service:");
@@ -528,6 +554,14 @@
}
/**
+ * @return true if this input method supports inline suggestions.
+ * @hide
+ */
+ public boolean isInlineSuggestionsEnabled() {
+ return mInlineSuggestionsEnabled;
+ }
+
+ /**
* Used to package this object into a {@link Parcel}.
*
* @param dest The {@link Parcel} to be written.
@@ -540,6 +574,7 @@
dest.writeInt(mIsDefaultResId);
dest.writeInt(mIsAuxIme ? 1 : 0);
dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
+ dest.writeInt(mInlineSuggestionsEnabled ? 1 : 0);
dest.writeBoolean(mIsVrOnly);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index abfbc6c..4329a20 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -20,6 +20,7 @@
import android.view.textclassifier.SelectionEvent.InvocationMethod;
import com.android.internal.util.Preconditions;
+
import java.util.Objects;
/**
@@ -183,6 +184,7 @@
mSmartEvent = event;
break;
case SelectionEvent.ACTION_ABANDON:
+ case SelectionEvent.ACTION_OVERTYPE:
if (mPrevEvent != null) {
event.setEntityType(mPrevEvent.getEntityType());
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 3b6a009..f6aaa6f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -139,6 +139,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Helper class used by TextView to handle editable text views.
@@ -7062,11 +7063,11 @@
private final List<ResolveInfo> mSupportedActivities = new ArrayList<>();
private ProcessTextIntentActionsHandler(Editor editor) {
- mEditor = Preconditions.checkNotNull(editor);
- mTextView = Preconditions.checkNotNull(mEditor.mTextView);
- mContext = Preconditions.checkNotNull(mTextView.getContext());
- mPackageManager = Preconditions.checkNotNull(mContext.getPackageManager());
- mPackageName = Preconditions.checkNotNull(mContext.getPackageName());
+ mEditor = Objects.requireNonNull(editor);
+ mTextView = Objects.requireNonNull(mEditor.mTextView);
+ mContext = Objects.requireNonNull(mTextView.getContext());
+ mPackageManager = Objects.requireNonNull(mContext.getPackageManager());
+ mPackageName = Objects.requireNonNull(mContext.getPackageName());
}
/**
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index f58b6d1..2924dd9 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -62,6 +62,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Android magnifier widget. Can be used by any view which is attached to a window.
@@ -1154,7 +1155,7 @@
* @param view the view this magnifier is attached to
*/
public Builder(@NonNull View view) {
- mView = Preconditions.checkNotNull(view);
+ mView = Objects.requireNonNull(view);
applyDefaults();
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index d0f8093..4ef3f61 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -87,7 +87,7 @@
private final SmartSelectSprite mSmartSelectSprite;
SelectionActionModeHelper(@NonNull Editor editor) {
- mEditor = Preconditions.checkNotNull(editor);
+ mEditor = Objects.requireNonNull(editor);
mTextView = mEditor.getTextView();
mTextClassificationHelper = new TextClassificationHelper(
mTextView.getContext(),
@@ -500,7 +500,7 @@
private final LogAbandonRunnable mDelayedLogAbandon = new LogAbandonRunnable();
SelectionTracker(TextView textView) {
- mTextView = Preconditions.checkNotNull(textView);
+ mTextView = Objects.requireNonNull(textView);
mLogger = new SelectionMetricsLogger(textView);
}
@@ -703,7 +703,7 @@
private String mText;
SelectionMetricsLogger(TextView textView) {
- Preconditions.checkNotNull(textView);
+ Objects.requireNonNull(textView);
mEditTextLogger = textView.isTextEditable();
mTokenIterator = SelectionSessionLogger.getTokenIterator(textView.getTextLocale());
}
@@ -714,7 +714,7 @@
CharSequence text, int index,
@InvocationMethod int invocationMethod) {
try {
- Preconditions.checkNotNull(text);
+ Objects.requireNonNull(text);
Preconditions.checkArgumentInRange(index, 0, text.length(), "index");
if (mText == null || !mText.contentEquals(text)) {
mText = text.toString();
@@ -972,11 +972,11 @@
@NonNull Consumer<SelectionResult> selectionResultCallback,
@NonNull Supplier<SelectionResult> timeOutResultSupplier) {
super(textView != null ? textView.getHandler() : null);
- mTextView = Preconditions.checkNotNull(textView);
+ mTextView = Objects.requireNonNull(textView);
mTimeOutDuration = timeOut;
- mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier);
- mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback);
- mTimeOutResultSupplier = Preconditions.checkNotNull(timeOutResultSupplier);
+ mSelectionResultSupplier = Objects.requireNonNull(selectionResultSupplier);
+ mSelectionResultCallback = Objects.requireNonNull(selectionResultCallback);
+ mTimeOutResultSupplier = Objects.requireNonNull(timeOutResultSupplier);
// Make a copy of the original text.
mOriginalText = getText(mTextView).toString();
}
@@ -1051,14 +1051,14 @@
TextClassificationHelper(Context context, Supplier<TextClassifier> textClassifier,
CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
init(textClassifier, text, selectionStart, selectionEnd, locales);
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
}
@UiThread
public void init(Supplier<TextClassifier> textClassifier, CharSequence text,
int selectionStart, int selectionEnd, LocaleList locales) {
- mTextClassifier = Preconditions.checkNotNull(textClassifier);
- mText = Preconditions.checkNotNull(text).toString();
+ mTextClassifier = Objects.requireNonNull(textClassifier);
+ mText = Objects.requireNonNull(text).toString();
mLastClassificationText = null; // invalidate.
Preconditions.checkArgument(selectionEnd > selectionStart);
mSelectionStart = selectionStart;
diff --git a/core/java/android/widget/SmartSelectSprite.java b/core/java/android/widget/SmartSelectSprite.java
index 9a84f69..dc472e1 100644
--- a/core/java/android/widget/SmartSelectSprite.java
+++ b/core/java/android/widget/SmartSelectSprite.java
@@ -38,13 +38,12 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
/**
* A utility class for creating and animating the Smart Select animation.
@@ -75,7 +74,7 @@
private final int mTextSelectionLayout;
RectangleWithTextSelectionLayout(RectF rectangle, int textSelectionLayout) {
- mRectangle = Preconditions.checkNotNull(rectangle);
+ mRectangle = Objects.requireNonNull(rectangle);
mTextSelectionLayout = textSelectionLayout;
}
@@ -342,7 +341,7 @@
context,
android.R.interpolator.fast_out_linear_in);
mFillColor = highlightColor;
- mInvalidator = Preconditions.checkNotNull(invalidator);
+ mInvalidator = Objects.requireNonNull(invalidator);
}
/**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a86b566..06e96d5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -98,10 +98,10 @@
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
+import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;
@@ -1546,6 +1546,21 @@
return -1;
}
+ @Override
+ protected boolean shouldAddFooterView() {
+ // To accommodate for window insets
+ return true;
+ }
+
+ @Override
+ protected void applyFooterView(int height) {
+ int count = mChooserMultiProfilePagerAdapter.getItemCount();
+
+ for (int i = 0; i < count; i++) {
+ mChooserMultiProfilePagerAdapter.getAdapterForIndex(i).setFooterHeight(height);
+ }
+ }
+
void queryTargetServices(ChooserListAdapter adapter) {
mQueriedTargetServicesTimeMs = System.currentTimeMillis();
@@ -2413,12 +2428,17 @@
}
/**
- * Intentionally override the {@link ResolverActivity} implementation as we only need that
- * implementation for the intent resolver case.
+ * Add a footer to the list, to support scrolling behavior below the navbar.
*/
- @Override
- protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
- return insets.consumeSystemWindowInsets();
+ final class FooterViewHolder extends RecyclerView.ViewHolder {
+ FooterViewHolder(View itemView) {
+ super(itemView);
+ }
+
+ public void setHeight(int height) {
+ itemView.setLayoutParams(
+ new RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, height));
+ }
}
/**
@@ -2451,11 +2471,14 @@
private boolean mLayoutRequested = false;
+ private FooterViewHolder mFooterViewHolder;
+
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_PROFILE = 2;
private static final int VIEW_TYPE_AZ_LABEL = 3;
private static final int VIEW_TYPE_CALLER_AND_RANK = 4;
+ private static final int VIEW_TYPE_FOOTER = 5;
private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
@@ -2467,6 +2490,9 @@
mChooserListAdapter = wrappedAdapter;
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
+ mFooterViewHolder = new FooterViewHolder(
+ new Space(ChooserActivity.this.getApplicationContext()));
+
mShowAzLabelIfPoss = getNumSheetExpansions() < NUM_EXPANSIONS_TO_HIDE_AZ_LABEL;
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -2484,6 +2510,10 @@
});
}
+ public void setFooterHeight(int height) {
+ mFooterViewHolder.setHeight(height);
+ }
+
/**
* Calculate the chooser target width to maximize space per item
*
@@ -2534,6 +2564,10 @@
return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
}
+ public int getFooterRowCount() {
+ return 1;
+ }
+
public int getCallerAndRankedTargetRowCount() {
return (int) Math.ceil(
((float) mChooserListAdapter.getCallerTargetCount()
@@ -2563,6 +2597,7 @@
+ getCallerAndRankedTargetRowCount()
+ getAzLabelRowCount()
+ mChooserListAdapter.getAlphaTargetCount()
+ + getFooterRowCount()
);
}
@@ -2578,6 +2613,8 @@
case VIEW_TYPE_DIRECT_SHARE:
case VIEW_TYPE_CALLER_AND_RANK:
return createItemGroupViewHolder(viewType, parent);
+ case VIEW_TYPE_FOOTER:
+ return mFooterViewHolder;
default:
// Since we catch all possible viewTypes above, no chance this is being called.
return null;
@@ -2615,6 +2652,8 @@
countSum += (count = getAzLabelRowCount());
if (count > 0 && position < countSum) return VIEW_TYPE_AZ_LABEL;
+ if (position == getItemCount() - 1) return VIEW_TYPE_FOOTER;
+
return VIEW_TYPE_NORMAL;
}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 46025aa..4e764fc 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -31,9 +31,11 @@
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
// and not be reordered
int checkOperation(int code, int uid, String packageName);
- int noteOperation(int code, int uid, String packageName, @nullable String featureId);
+ int noteOperation(int code, int uid, String packageName, @nullable String featureId,
+ boolean shouldCollectAsyncNotedOp, String message);
int startOperation(IBinder clientId, int code, int uid, String packageName,
- @nullable String featureId, boolean startIfModeDefault);
+ @nullable String featureId, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message);
@UnsupportedAppUsage
void finishOperation(IBinder clientId, int code, int uid, String packageName,
@nullable String featureId);
@@ -41,8 +43,6 @@
void stopWatchingMode(IAppOpsCallback callback);
int permissionToOpCode(String permission);
int checkAudioOperation(int code, int usage, int uid, String packageName);
- void noteAsyncOp(@nullable String callingPackageName, int uid, @nullable String packageName,
- int opCode, @nullable String featureId, String message);
boolean shouldCollectNotes(int opCode);
void setCameraAudioRestriction(int mode);
// End of methods also called by native code.
@@ -50,7 +50,7 @@
int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedFeatureId, int proxyUid, String proxyPackageName,
- String proxyFeatureId);
+ String proxyFeatureId, boolean shouldCollectAsyncNotedOp, String message);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 8dc3a07..8d3c572 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -353,7 +353,11 @@
finish();
}
});
- if (isVoiceInteraction()) {
+
+ boolean hasTouchScreen = getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+
+ if (isVoiceInteraction() || !hasTouchScreen) {
rdl.setCollapsed(false);
}
@@ -472,34 +476,52 @@
finish();
}
+ /**
+ * Numerous layouts are supported, each with optional ViewGroups.
+ * Make sure the inset gets added to the correct View, using
+ * a footer for Lists so it can properly scroll under the navbar.
+ */
+ protected boolean shouldAddFooterView() {
+ if (useLayoutWithDefault()) return true;
+
+ View buttonBar = findViewById(R.id.button_bar);
+ if (buttonBar == null || buttonBar.getVisibility() == View.GONE) return true;
+
+ return false;
+ }
+
+ protected void applyFooterView(int height) {
+ if (mFooterSpacer == null) {
+ mFooterSpacer = new Space(getApplicationContext());
+ } else {
+ ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+ .getCurrentAdapterView().removeFooterView(mFooterSpacer);
+ }
+ mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
+ mSystemWindowInsets.bottom));
+ ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+ .getCurrentAdapterView().addFooterView(mFooterSpacer);
+ }
+
protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
mSystemWindowInsets = insets.getSystemWindowInsets();
mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
mSystemWindowInsets.right, 0);
+ resetButtonBar();
+
// Need extra padding so the list can fully scroll up
- if (useLayoutWithDefault()) {
- if (mFooterSpacer == null) {
- mFooterSpacer = new Space(getApplicationContext());
- } else {
- ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
- .getCurrentAdapterView().removeFooterView(mFooterSpacer);
- }
- mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
- mSystemWindowInsets.bottom));
- ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
- .getCurrentAdapterView().addFooterView(mFooterSpacer);
- } else {
- View emptyView = findViewById(R.id.empty);
- if (emptyView != null) {
- emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
- + getResources().getDimensionPixelSize(
- R.dimen.chooser_edge_margin_normal) * 2);
- }
+ if (shouldAddFooterView()) {
+ applyFooterView(mSystemWindowInsets.bottom);
}
- resetButtonBar();
+ View emptyView = findViewById(R.id.empty);
+ if (emptyView != null) {
+ emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+ + getResources().getDimensionPixelSize(
+ R.dimen.chooser_edge_margin_normal) * 2);
+ }
return insets.consumeSystemWindowInsets();
}
@@ -1283,10 +1305,11 @@
// In case this method is called again (due to activity recreation), avoid adding a new
// header if one is already present.
- if (useHeader && listView != null && listView.getHeaderViewsCount() == 0) {
+ if (useHeader && listView.getHeaderViewsCount() == 0) {
listView.setHeaderDividersEnabled(true);
listView.addHeaderView(LayoutInflater.from(this).inflate(
- R.layout.resolver_different_item_header, listView, false));
+ R.layout.resolver_different_item_header, listView, false),
+ null, false);
}
}
@@ -1349,6 +1372,8 @@
if (useLayoutWithDefault() && filteredPosition != ListView.INVALID_POSITION) {
setAlwaysButtonEnabled(true, filteredPosition, false);
mOnceButton.setEnabled(true);
+ // Focus the button if we already have the default option
+ mOnceButton.requestFocus();
return;
}
@@ -1481,6 +1506,7 @@
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
currentAdapterView.smoothScrollToPosition(checkedPos);
+ mOnceButton.requestFocus();
}
mLastSelected = checkedPos;
} else {
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index 857377a..e9d7d05 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -223,7 +223,7 @@
private final @NonNull ServiceConnection mServiceConnection = this;
private final @NonNull Runnable mTimeoutDisconnect = this;
- private final @NonNull Context mContext;
+ protected final @NonNull Context mContext;
private final @NonNull Intent mIntent;
private final int mBindingFlags;
private final int mUserId;
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 4a21d37..8d281b7 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -184,9 +184,8 @@
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
- fetchUsapPoolPolicyProps();
-
mUsapPoolSupported = true;
+ fetchUsapPoolPolicyProps();
}
void setForkChild() {
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index 362bc92..580c2fa 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -107,9 +107,12 @@
* Amount of RAM that is in use by the kernel for actual allocations.
*/
public long getKernelUsedSizeKb() {
- return mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
- + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES]
- + mInfos[Debug.MEMINFO_KERNEL_STACK];
+ long size = mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
+ + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES];
+ if (!Debug.isVmapStack()) {
+ size += mInfos[Debug.MEMINFO_KERNEL_STACK];
+ }
+ return size;
}
public long getSwapTotalSizeKb() {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 1bb2ba2..e0c3823 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -187,7 +187,7 @@
public void setCollapsed(boolean collapsed) {
if (!isLaidOut()) {
- mOpenOnLayout = collapsed;
+ mOpenOnLayout = !collapsed;
} else {
smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0);
}
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index 2265268..79f62cb 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -59,7 +59,6 @@
jfieldID hasFocus;
jfieldID hasWallpaper;
jfieldID paused;
- jfieldID layer;
jfieldID ownerPid;
jfieldID ownerUid;
jfieldID inputFeatures;
@@ -152,8 +151,6 @@
gInputWindowHandleClassInfo.hasWallpaper);
mInfo.paused = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.paused);
- mInfo.layer = env->GetIntField(obj,
- gInputWindowHandleClassInfo.layer);
mInfo.ownerPid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerPid);
mInfo.ownerUid = env->GetIntField(obj,
@@ -332,9 +329,6 @@
GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
"paused", "Z");
- GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
- "layer", "I");
-
GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
"ownerPid", "I");
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 6e0d5d8..4314eb6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -50,6 +50,7 @@
#include <memunreachable/memunreachable.h>
#include <android-base/strings.h>
#include "android_os_Debug.h"
+#include <vintf/VintfObject.h>
namespace android
{
@@ -835,6 +836,23 @@
return ionPss;
}
+static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
+{
+ static enum {
+ CONFIG_UNKNOWN,
+ CONFIG_SET,
+ CONFIG_UNSET,
+ } cfg_state = CONFIG_UNKNOWN;
+
+ if (cfg_state == CONFIG_UNKNOWN) {
+ const std::map<std::string, std::string> configs =
+ vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs();
+ std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
+ cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
+ }
+ return cfg_state == CONFIG_SET;
+}
+
/*
* JNI registration.
*/
@@ -884,6 +902,8 @@
(void*)android_os_Debug_getIonPoolsSizeKb },
{ "getIonMappedSizeKb", "()J",
(void*)android_os_Debug_getIonMappedSizeKb },
+ { "isVmapStack", "()Z",
+ (void*)android_os_Debug_isVmapStack },
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7719165..5410cf5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3591,6 +3591,11 @@
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to start and stop one time permission sessions
+ @hide -->
+ <permission android:name="android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"
+ android:protectionLevel="signature|installer" />
+
<!-- @SystemApi Allows an application to manage the holders of a role.
@hide
STOPSHIP b/145526313: Remove wellbeing protection flag from MANAGE_ROLE_HOLDERS. -->
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index eb1f553..68708d35 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -440,7 +440,7 @@
<string name="permlab_callPhone" msgid="1798582257194643320">"اتصال مباشر بأرقام الهواتف"</string>
<string name="permdesc_callPhone" msgid="5439809516131609109">"للسماح للتطبيق بطلب أرقام هاتفية بدون تدخل منك. وقد يؤدي ذلك إلى تحمل رسوم غير متوقعة أو إجراء مكالمات غير متوقعة. ومن الجدير بالذكر أن ذلك لا يتيح للتطبيق الاتصال بأرقام الطوارئ. وقد تؤدي التطبيقات الضارة إلى تحملك تكاليف مالية من خلال إجراء مكالمات بدون موافقة منك."</string>
<string name="permlab_accessImsCallService" msgid="442192920714863782">"الوصول إلى خدمة الاتصال عبر الرسائل الفورية"</string>
- <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"للسماح للتطبيق باستخدام خدمة الرسائل الفورية لإجراء المكالمات دون تدخل منك."</string>
+ <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"للسماح للتطبيق باستخدام خدمة الرسائل الفورية لإجراء المكالمات بدون تدخل منك."</string>
<string name="permlab_readPhoneState" msgid="8138526903259297969">"قراءة حالة الهاتف والهوية"</string>
<string name="permdesc_readPhoneState" msgid="7229063553502788058">"للسماح للتطبيق بالدخول إلى ميزات الهاتف في الجهاز. ويتيح هذا الإذن للتطبيق تحديد رقم الهاتف ومعرّفات الجهاز، وما إذا كانت هناك مكالمة نشطة والرقم البعيد الذي تم الاتصال به في المكالمة."</string>
<string name="permlab_manageOwnCalls" msgid="9033349060307561370">"توجيه المكالمات من خلال النظام"</string>
@@ -1283,7 +1283,7 @@
<string name="heavy_weight_switcher_text" msgid="6814316627367160126">"للحصول على أداء أفضل، يمكن فتح لعبة واحدة فقط من هذه الألعاب في كل مرة."</string>
<string name="old_app_action" msgid="725331621042848590">"الرجوع إلى <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="new_app_action" msgid="547772182913269801">"فتح <xliff:g id="NEW_APP">%1$s</xliff:g>"</string>
- <string name="new_app_description" msgid="1958903080400806644">"سيتم إغلاق <xliff:g id="OLD_APP">%1$s</xliff:g> من دون حفظ"</string>
+ <string name="new_app_description" msgid="1958903080400806644">"سيتم إغلاق <xliff:g id="OLD_APP">%1$s</xliff:g> بدون حفظ"</string>
<string name="dump_heap_notification" msgid="5316644945404825032">"لقد تجاوزت <xliff:g id="PROC">%1$s</xliff:g> حد الذاكرة."</string>
<string name="dump_heap_ready_notification" msgid="2302452262927390268">"نَسْخ الذاكرة <xliff:g id="PROC">%1$s</xliff:g> جاهز"</string>
<string name="dump_heap_notification_detail" msgid="8431586843001054050">"تم جمع مقدار كبير من بيانات الذاكرة. انقر للمشاركة."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6928a14..612854c 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1855,11 +1855,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> से कनेक्ट किया गया"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"फ़ाइलें देखने के लिए टैप करें"</string>
<string name="pin_target" msgid="8036028973110156895">"पिन करें"</string>
- <!-- no translation found for pin_specific_target (7824671240625957415) -->
- <skip />
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> को पिन करें"</string>
<string name="unpin_target" msgid="3963318576590204447">"अनपिन करें"</string>
- <!-- no translation found for unpin_specific_target (3859828252160908146) -->
- <skip />
+ <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> को अनपिन करें"</string>
<string name="app_info" msgid="6113278084877079851">"ऐप्लिकेशन की जानकारी"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"डेमो प्रारंभ हो रहा है…"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index aa28bf2..3e23679 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -665,7 +665,7 @@
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Sletter denne brukerens data på dette nettbrettet uten advarsel."</string>
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Tøm dataene til denne brukeren på denne Android TV-enheten uten advarsel."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Sletter denne brukerens data på denne telefonen uten advarsel."</string>
- <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Angi enhetens globale mellomtjener"</string>
+ <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Angi enhetens globale proxy-tjener"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Angir den globale proxy-tjeneren på enheten som skal brukes når regelen er aktivert. Bare eieren av enheten kan angi den globale proxy-tjeneren."</string>
<string name="policylab_expirePassword" msgid="6015404400532459169">"Angi utløpstid for skjermlås"</string>
<string name="policydesc_expirePassword" msgid="9136524319325960675">"Endrer hvor ofte PIN-koden, passordet eller mønsteret til skjermlåsen skal byttes."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index be173dd..7aa91f7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -497,10 +497,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Aplikaciji omogoča ogled konfiguracije Bluetootha tabličnega računalnika ter vzpostavljanje in sprejemanje povezave s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Aplikaciji dovoljuje ogled konfiguracije vmesnika Bluetooth v napravi Android TV ter ustvarjanje in sprejemanje povezav s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Aplikaciji omogoča ogled konfiguracije Bluetootha telefona ter ustvarjanje in sprejemanje povezave s seznanjenimi napravami."</string>
- <!-- no translation found for permlab_preferredPaymentInfo (5274423844767445054) -->
- <skip />
- <!-- no translation found for permdesc_preferredPaymentInfo (8583552469807294967) -->
- <skip />
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Podatki o prednostni storitvi za plačevanje prek povezave NFC"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Aplikaciji omogoča pridobivanje podatkov o prednostni storitvi za plačevanje prek povezave NFC, kot so registrirani pripomočki in cilj preusmeritve."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"onemogočanje zaklepanja zaslona"</string>
@@ -1663,12 +1661,6 @@
<string name="accessibility_shortcut_enabling_service" msgid="6141620395915529473">"Bližnjica funkcij za ljudi s posebnimi potrebami je vklopila <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="1287340429965172651">"Bližnjica funkcij za ljudi s posebnimi potrebami je izklopila <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Za uporabo storitve <xliff:g id="SERVICE_NAME">%1$s</xliff:g> pritisnite obe tipki za glasnost in ju pridržite tri sekunde"</string>
- <string name="accessibility_button_prompt_text" msgid="1634298854002673171">"Izberite storitev, ki jo želite uporabljati, ko se dotaknete gumba za funkcije za ljudi s posebnimi potrebami:"</string>
- <string name="accessibility_gesture_prompt_text" msgid="3271927619707898924">"Izberite storitev, ki jo želite zagnati s potezo za ljudi s posebnimi potrebami (vlečenje z dvema prstoma z dna zaslona navzgor):"</string>
- <string name="accessibility_gesture_3finger_prompt_text" msgid="218295923313037542">"Izberite storitev, ki jo želite zagnati s potezo za ljudi s posebnimi potrebami (vlečenje s tremi prsti z dna zaslona navzgor):"</string>
- <string name="accessibility_button_instructional_text" msgid="8523635009916665153">"Če želite preklopiti med storitvami, pridržite gumb za funkcije za ljudi s posebnimi potrebami."</string>
- <string name="accessibility_gesture_instructional_text" msgid="927882482331885974">"Če želite preklopiti med storitvami, z dvema prstoma povlecite navzgor in pridržite."</string>
- <string name="accessibility_gesture_3finger_instructional_text" msgid="7527523742771203377">"Če želite preklopiti med storitvami, s tremi prsti povlecite navzgor in pridržite."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Povečava"</string>
<string name="user_switched" msgid="7249833311585228097">"Trenutni uporabnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"Preklop na uporabnika <xliff:g id="NAME">%1$s</xliff:g> …"</string>
@@ -1927,11 +1919,9 @@
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Vzpostavljena povezava z napravo <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Dotaknite se, če si želite ogledati datoteke"</string>
<string name="pin_target" msgid="8036028973110156895">"Pripenjanje"</string>
- <!-- no translation found for pin_specific_target (7824671240625957415) -->
- <skip />
+ <string name="pin_specific_target" msgid="7824671240625957415">"Pripni aplikacijo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="unpin_target" msgid="3963318576590204447">"Odpenjanje"</string>
- <!-- no translation found for unpin_specific_target (3859828252160908146) -->
- <skip />
+ <string name="unpin_specific_target" msgid="3859828252160908146">"Odpni aplikacijo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="app_info" msgid="6113278084877079851">"Podatki o aplikacijah"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="demo_starting_message" msgid="6577581216125805905">"Začenjanje predstavitve …"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d01e8e7..2cc42d7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -491,8 +491,8 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"允許應用程式查看 Android TV 裝置的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
- <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"首選 NFC 付款服務資訊"</string>
- <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得首選 NFC 付款服務的資訊 (如已註冊的付款輔助和最終付款對象)。"</string>
+ <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"由用戶允許授權的 NFC 付款服務資訊"</string>
+ <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"允許應用程式取得由用戶允許授權的 NFC 付款服務資訊 (如已註冊的付款輔助功能和最終付款對象)。"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"控制近距離無線通訊"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
<string name="permlab_disableKeyguard" msgid="3605253559020928505">"停用螢幕上鎖"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 38d3e9c..9c08728 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3469,6 +3469,8 @@
device -->
<attr name="isVrOnly" format="boolean"/>
<attr name="__removed2" format="boolean" />
+ <!-- Specifies whether the IME supports showing inline suggestions. -->
+ <attr name="supportsInlineSuggestions" format="boolean" />
</declare-styleable>
<!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
@@ -8177,6 +8179,9 @@
<!-- Fully qualified class name of an activity that allows the user to modify
the settings for this service. -->
<attr name="settingsActivity" />
+
+ <!-- Specifies whether the AutofillService supports inline suggestions-->
+ <attr name="supportsInlineSuggestions" format="boolean" />
</declare-styleable>
<!-- Use <code>compatibility-package</code> as a child tag of <code>autofill-service</code>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 85f7d61..6435cdd 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1533,7 +1533,8 @@
<code>com.google.app.<em>appname</em></code>
<p>Inside of the manifest tag, may appear the following tags
- in any order: {@link #AndroidManifestPermission permission},
+ in any order: {@link #AndroidManifestFeature feature},
+ {@link #AndroidManifestPermission permission},
{@link #AndroidManifestPermissionGroup permission-group},
{@link #AndroidManifestPermissionTree permission-tree},
{@link #AndroidManifestUsesSdk uses-sdk},
@@ -1763,6 +1764,29 @@
The default value is {@code false}. -->
<attr name="crossProfile" format="boolean" />
</declare-styleable>
+
+ <!-- The <code>feature</code> tag declares a feature. A feature is a part of an app. E.g.
+ photo sharing app might include a direct messaging component.
+
+ <p>This appears as a child tag of the root {@link #AndroidManifest manifest} tag.
+
+ <p>In case this feature inherits from another feature, this tag can contain one or multiple
+ {@link #AndroidManifestFeatureInheritFrom inherit-from} tags. -->
+ <declare-styleable name="AndroidManifestFeature" parent="AndroidManifest">
+ <!-- Required identifier for a feature. Can be passed to
+ {@link android.content.Context#createFeatureContext} to create a context for this feature
+ -->
+ <attr name="featureId" format="string" />
+ <!-- Required user visible label for a feature. -->
+ <attr name="label" format="string" />
+ </declare-styleable>
+
+ <!-- Declares previously declared features this feature inherits from. -->
+ <declare-styleable name="AndroidManifestFeatureInheritFrom" parent="AndroidManifestFeature">
+ <!-- Identifier of the feature this feature inherits from -->
+ <attr name="featureId" format="string" />
+ </declare-styleable>
+
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
features in your package (or other packages). See the
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0b63518..d12d069 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3004,6 +3004,9 @@
<public name="resourcesMap" />
<public name="animatedImageDrawable"/>
<public name="htmlDescription"/>
+ <public name="preferMinimalPostProcessing"/>
+ <public name="featureId" />
+ <public name="supportsInlineSuggestions" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
@@ -3049,10 +3052,6 @@
<public name="accessibilitySystemActionLockScreen" />
<public name="accessibilitySystemActionTakeScreenshot" />
</public-group>
-
- <public-group type="attr" first-id="0x0101060c">
- <public name="preferMinimalPostProcessing"/>
- </public-group>
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e874ac7..a00296c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3209,11 +3209,6 @@
<java-symbol type="id" name="accessibility_button_target_label" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" />
- <java-symbol type="string" name="accessibility_gesture_prompt_text" />
- <java-symbol type="string" name="accessibility_gesture_3finger_prompt_text" />
- <java-symbol type="string" name="accessibility_gesture_instructional_text" />
- <java-symbol type="string" name="accessibility_gesture_3finger_instructional_text" />
-
<java-symbol type="drawable" name="ic_accessibility_magnification" />
<!-- com.android.internal.widget.RecyclerView -->
diff --git a/core/tests/coretests/res/xml/ime_meta_inline_suggestions.xml b/core/tests/coretests/res/xml/ime_meta_inline_suggestions.xml
new file mode 100644
index 0000000..e67bf63
--- /dev/null
+++ b/core/tests/coretests/res/xml/ime_meta_inline_suggestions.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<input-method
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity"
+ android:supportsInlineSuggestions="true"
+>
+ <subtype
+ android:label="subtype1"
+ android:imeSubtypeLocale="en_US"
+ android:imeSubtypeMode="keyboard" />
+</input-method>
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index f24e232..8718b95 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -54,10 +54,12 @@
final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta);
assertThat(imi.supportsSwitchingToNextInputMethod(), is(false));
+ assertThat(imi.isInlineSuggestionsEnabled(), is(false));
final InputMethodInfo clone = cloneViaParcel(imi);
assertThat(clone.supportsSwitchingToNextInputMethod(), is(false));
+ assertThat(imi.isInlineSuggestionsEnabled(), is(false));
}
@Test
@@ -72,6 +74,17 @@
}
@Test
+ public void testInlineSuggestionsEnabled() throws Exception {
+ final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_inline_suggestions);
+
+ assertThat(imi.isInlineSuggestionsEnabled(), is(true));
+
+ final InputMethodInfo clone = cloneViaParcel(imi);
+
+ assertThat(clone.isInlineSuggestionsEnabled(), is(true));
+ }
+
+ @Test
public void testIsVrOnly() throws Exception {
final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_vr_only);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index c3ef1c8..fbe4c1a 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -1022,23 +1022,11 @@
@Test
public void testSelectionMetricsLogger_abandonEventIncludesEntityType() throws Throwable {
- final List<SelectionEvent> selectionEvents = new ArrayList<>();
- final TextClassifier classifier = new TextClassifier() {
- @Override
- public void onSelectionEvent(SelectionEvent event) {
- selectionEvents.add(event);
- }
-
- @Override
- public TextSelection suggestSelection(TextSelection.Request request) {
- return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex())
- .setEntityType(TextClassifier.TYPE_PHONE, 1)
- .build();
- }
- };
+ final TestableTextClassifier classifier = new TestableTextClassifier();
final TextView textView = mActivity.findViewById(R.id.textview);
mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier));
mInstrumentation.waitForIdleSync();
+
final String text = "My number is 987654321";
onView(withId(R.id.textview)).perform(replaceText(text));
@@ -1053,6 +1041,7 @@
long waitTime = 0;
SelectionEvent lastEvent;
do {
+ final List<SelectionEvent> selectionEvents = classifier.getSelectionEvents();
lastEvent = selectionEvents.get(selectionEvents.size() - 1);
if (lastEvent.getEventType() == SelectionEvent.ACTION_ABANDON) {
break;
@@ -1061,6 +1050,29 @@
waitTime += pollInterval;
} while (waitTime < abandonDelay * 10);
assertEquals(SelectionEvent.ACTION_ABANDON, lastEvent.getEventType());
+ }
+
+ @Test
+ public void testSelectionMetricsLogger_overtypeEventIncludesEntityType() throws Throwable {
+ final TestableTextClassifier classifier = new TestableTextClassifier();
+ final TextView textView = mActivity.findViewById(R.id.textview);
+ mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier));
+ mInstrumentation.waitForIdleSync();
+
+ final String text = "My number is 987654321";
+
+ // Long press to trigger selection
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('9')));
+ sleepForFloatingToolbarPopup();
+
+ // Type over the selection
+ onView(withId(R.id.textview)).perform(pressKey(KeyEvent.KEYCODE_A));
+ mInstrumentation.waitForIdleSync();
+
+ final List<SelectionEvent> selectionEvents = classifier.getSelectionEvents();
+ final SelectionEvent lastEvent = selectionEvents.get(selectionEvents.size() - 1);
+ assertEquals(SelectionEvent.ACTION_OVERTYPE, lastEvent.getEventType());
assertEquals(TextClassifier.TYPE_PHONE, lastEvent.getEntityType());
}
@@ -1115,4 +1127,24 @@
private enum TextStyle {
PLAIN, STYLED
}
+
+ private final class TestableTextClassifier implements TextClassifier {
+ final List<SelectionEvent> mSelectionEvents = new ArrayList<>();
+
+ @Override
+ public void onSelectionEvent(SelectionEvent event) {
+ mSelectionEvents.add(event);
+ }
+
+ @Override
+ public TextSelection suggestSelection(TextSelection.Request request) {
+ return new TextSelection.Builder(request.getStartIndex(), request.getEndIndex())
+ .setEntityType(TextClassifier.TYPE_PHONE, 1)
+ .build();
+ }
+
+ List<SelectionEvent> getSelectionEvents() {
+ return mSelectionEvents;
+ }
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 8622b7e..c086421 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -54,6 +54,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -977,6 +978,7 @@
serviceTargets,
TARGET_TYPE_CHOOSER_TARGET)
);
+
// Thread.sleep shouldn't be a thing in an integration test but it's
// necessary here because of the way the code is structured
// TODO: restructure the tests b/129870719
@@ -1075,7 +1077,29 @@
// This test is too long and too slow and should not be taken as an example for future tests.
@Test
- public void testDirectTargetLoggingWithAppTargetNotRanked() throws InterruptedException {
+ public void testDirectTargetLoggingWithAppTargetNotRankedPortrait()
+ throws InterruptedException {
+ testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_PORTRAIT, 4);
+ }
+
+ @Test
+ public void testDirectTargetLoggingWithAppTargetNotRankedLandscape()
+ throws InterruptedException {
+ testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_LANDSCAPE, 8);
+ }
+
+ private void testDirectTargetLoggingWithAppTargetNotRanked(
+ int orientation, int appTargetsExpected
+ ) throws InterruptedException {
+ Configuration configuration =
+ new Configuration(InstrumentationRegistry.getInstrumentation().getContext()
+ .getResources().getConfiguration());
+ configuration.orientation = orientation;
+
+ sOverrides.resources = Mockito.spy(
+ InstrumentationRegistry.getInstrumentation().getContext().getResources());
+ when(sOverrides.resources.getConfiguration()).thenReturn(configuration);
+
Intent sendIntent = createSendTextIntent();
// We need app targets for direct targets to get displayed
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
@@ -1111,8 +1135,10 @@
// TODO: restructure the tests b/129870719
Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
- assertThat("Chooser should have 20 targets (4 apps, 1 direct, 15 A-Z)",
- activity.getAdapter().getCount(), is(20));
+ assertThat(
+ String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)",
+ appTargetsExpected + 16, appTargetsExpected),
+ activity.getAdapter().getCount(), is(appTargetsExpected + 16));
assertThat("Chooser should have exactly one selectable direct target",
activity.getAdapter().getSelectableServiceTargetCount(), is(1));
assertThat("The resolver info must match the resolver info used to create the target",
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 9863e38..66d84aa 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -54,7 +54,6 @@
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -76,7 +75,6 @@
@RunWith(AndroidJUnit4.class)
@MediumTest
@Presubmit
-@FlakyTest(bugId = 143153552)
public class ActivityThreadClientTest {
@Test
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index f1941fc..38a9f46 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -130,7 +130,6 @@
<permission name="android.permission.APPROVE_INCIDENT_REPORTS"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
- <permission name="android.permission.PACKAGE_USAGE_STATS" />
</privapp-permissions>
<privapp-permissions package="com.android.phone">
diff --git a/media/Android.bp b/media/Android.bp
index a136517..499d0da 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,110 +1,3 @@
-java_library {
- name: "updatable-media",
-
- srcs: [
- ":updatable-media-srcs",
- ],
-
- aidl: {
- export_include_dirs: [
- "apex/java",
- ],
-
- // It would be great if we don't need to add include_dirs for public
- // parcelable classes. Find a better way.
- include_dirs: [
- // To refer:
- // android.os.Bundle
- // android.os.ResultReceiver
- "frameworks/base/core/java",
- ],
- },
-
- permitted_packages: [
- "android.media",
- ],
-
- installable: true,
-
- // TODO: build against stable API surface. Use core_platform for now to avoid
- // link-check failure with exoplayer building against "current".
- sdk_version: "core_platform",
- libs: [
- // The order matters. android_system_* library should come later.
- "framework_media_annotation",
- "android_system_stubs_current",
- ],
-
- static_libs: [
- "exoplayer2-core"
- ],
- jarjar_rules: "jarjar_rules.txt",
-
- plugins: ["java_api_finder"],
-}
-
-filegroup {
- name: "updatable-media-srcs",
- srcs: [
- ":mediaparser-srcs",
- ":mediasession2-srcs",
- ],
-}
-
-filegroup {
- name: "mediasession2-srcs",
- srcs: [
- "apex/java/android/media/Controller2Link.java",
- "apex/java/android/media/IMediaController2.aidl",
- "apex/java/android/media/IMediaSession2.aidl",
- "apex/java/android/media/IMediaSession2Service.aidl",
- "apex/java/android/media/MediaConstants.java",
- "apex/java/android/media/MediaController2.java",
- "apex/java/android/media/MediaSession2.java",
- "apex/java/android/media/MediaSession2Service.java",
- "apex/java/android/media/Session2Command.java",
- "apex/java/android/media/Session2CommandGroup.java",
- "apex/java/android/media/Session2Link.java",
- "apex/java/android/media/Session2Token.java",
- ],
- path: "apex/java",
-}
-
-filegroup {
- name: "mediaparser-srcs",
- srcs: [
- "apex/java/android/media/MediaParser.java"
- ],
- path: "apex/java"
-}
-
-droidstubs {
- name: "updatable-media-stubs",
- srcs: [
- ":updatable-media-srcs",
- ":framework-media-annotation-srcs",
- ],
- defaults: [ "framework-module-stubs-defaults-systemapi" ],
- aidl: {
- // TODO(b/135922046) remove this
- include_dirs: ["frameworks/base/core/java"],
- },
- sdk_version: "system_current",
-}
-
-java_library {
- name: "updatable_media_stubs",
- srcs: [":updatable-media-stubs"],
- sdk_version: "system_current",
-}
-
-java_library {
- name: "framework_media_annotation",
- srcs: [":framework-media-annotation-srcs"],
- installable: false,
- sdk_version: "core_current",
-}
-
aidl_interface {
name: "audio_common-aidl",
local_include_dir: "java",
diff --git a/media/apex/java/android/media/CloseGuard.java b/media/apex/java/android/media/CloseGuard.java
deleted file mode 100644
index 2014673..0000000
--- a/media/apex/java/android/media/CloseGuard.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.util.Log;
-
-/**
- * Note: This file is copied from dalvik.system package with the following modifications:
- * - Remove @CorePlatformApi, @IntraCoreApi and @UnsupportedAppUsage annotations.
- * - Replace System.logW() with android.util.Log.w().
- * This file should be used only within media mainline module.
- * TODO: Remove this file and use dalvik.system.CloseGuard once
- * @CorePlatformApi becomes stable or we have a replacement in SDK API.
- * b/120419300
- *
- * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
- * resources that should have been cleaned up by explicit close
- * methods (aka "explicit termination methods" in Effective Java).
- * <p>
- * A simple example: <pre> {@code
- * class Foo {
- *
- * {@literal @}ReachabilitySensitive
- * private final CloseGuard guard = CloseGuard.get();
- *
- * ...
- *
- * public Foo() {
- * ...;
- * guard.open("cleanup");
- * }
- *
- * public void cleanup() {
- * guard.close();
- * ...;
- * }
- *
- * protected void finalize() throws Throwable {
- * try {
- * // Note that guard could be null if the constructor threw.
- * if (guard != null) {
- * guard.warnIfOpen();
- * }
- * cleanup();
- * } finally {
- * super.finalize();
- * }
- * }
- * }
- * }</pre>
- *
- * In usage where the resource to be explicitly cleaned up is
- * allocated after object construction, CloseGuard protection can
- * be deferred. For example: <pre> {@code
- * class Bar {
- *
- * {@literal @}ReachabilitySensitive
- * private final CloseGuard guard = CloseGuard.get();
- *
- * ...
- *
- * public Bar() {
- * ...;
- * }
- *
- * public void connect() {
- * ...;
- * guard.open("cleanup");
- * }
- *
- * public void cleanup() {
- * guard.close();
- * ...;
- * }
- *
- * protected void finalize() throws Throwable {
- * try {
- * // Note that guard could be null if the constructor threw.
- * if (guard != null) {
- * guard.warnIfOpen();
- * }
- * cleanup();
- * } finally {
- * super.finalize();
- * }
- * }
- * }
- * }</pre>
- *
- * When used in a constructor, calls to {@code open} should occur at
- * the end of the constructor since an exception that would cause
- * abrupt termination of the constructor will mean that the user will
- * not have a reference to the object to cleanup explicitly. When used
- * in a method, the call to {@code open} should occur just after
- * resource acquisition.
- *
- * The @ReachabilitySensitive annotation ensures that finalize() cannot be
- * called during the explicit call to cleanup(), prior to the guard.close call.
- * There is an extremely small chance that, for code that neglects to call
- * cleanup(), finalize() and thus cleanup() will be called while a method on
- * the object is still active, but the "this" reference is no longer required.
- * If missing cleanup() calls are expected, additional @ReachabilitySensitive
- * annotations or reachabilityFence() calls may be required.
- *
- * @hide
- */
-final class CloseGuard {
-
- /**
- * True if collection of call-site information (the expensive operation
- * here) and tracking via a Tracker (see below) are enabled.
- * Enabled by default so we can diagnose issues early in VM startup.
- * Note, however, that Android disables this early in its startup,
- * but enables it with DropBoxing for system apps on debug builds.
- */
- private static volatile boolean stackAndTrackingEnabled = true;
-
- /**
- * Hook for customizing how CloseGuard issues are reported.
- * Bypassed if stackAndTrackingEnabled was false when open was called.
- */
- private static volatile Reporter reporter = new DefaultReporter();
-
- /**
- * Hook for customizing how CloseGuard issues are tracked.
- */
- private static volatile Tracker currentTracker = null; // Disabled by default.
-
- /**
- * Returns a CloseGuard instance. {@code #open(String)} can be used to set
- * up the instance to warn on failure to close.
- */
- public static CloseGuard get() {
- return new CloseGuard();
- }
-
- /**
- * Enables/disables stack capture and tracking. A call stack is captured
- * during open(), and open/close events are reported to the Tracker, only
- * if enabled is true. If a stack trace was captured, the {@link
- * #getReporter() reporter} is informed of unclosed resources; otherwise a
- * one-line warning is logged.
- */
- public static void setEnabled(boolean enabled) {
- CloseGuard.stackAndTrackingEnabled = enabled;
- }
-
- /**
- * True if CloseGuard stack capture and tracking are enabled.
- */
- public static boolean isEnabled() {
- return stackAndTrackingEnabled;
- }
-
- /**
- * Used to replace default Reporter used to warn of CloseGuard
- * violations when stack tracking is enabled. Must be non-null.
- */
- public static void setReporter(Reporter rep) {
- if (rep == null) {
- throw new NullPointerException("reporter == null");
- }
- CloseGuard.reporter = rep;
- }
-
- /**
- * Returns non-null CloseGuard.Reporter.
- */
- public static Reporter getReporter() {
- return reporter;
- }
-
- /**
- * Sets the {@link Tracker} that is notified when resources are allocated and released.
- * The Tracker is invoked only if CloseGuard {@link #isEnabled()} held when {@link #open()}
- * was called. A null argument disables tracking.
- *
- * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
- * MUST NOT be used for any other purposes.
- */
- public static void setTracker(Tracker tracker) {
- currentTracker = tracker;
- }
-
- /**
- * Returns {@link #setTracker(Tracker) last Tracker that was set}, or null to indicate
- * there is none.
- *
- * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
- * MUST NOT be used for any other purposes.
- */
- public static Tracker getTracker() {
- return currentTracker;
- }
-
- private CloseGuard() {}
-
- /**
- * {@code open} initializes the instance with a warning that the caller
- * should have explicitly called the {@code closer} method instead of
- * relying on finalization.
- *
- * @param closer non-null name of explicit termination method. Printed by warnIfOpen.
- * @throws NullPointerException if closer is null.
- */
- public void open(String closer) {
- // always perform the check for valid API usage...
- if (closer == null) {
- throw new NullPointerException("closer == null");
- }
- // ...but avoid allocating an allocation stack if "disabled"
- if (!stackAndTrackingEnabled) {
- closerNameOrAllocationInfo = closer;
- return;
- }
- String message = "Explicit termination method '" + closer + "' not called";
- Throwable stack = new Throwable(message);
- closerNameOrAllocationInfo = stack;
- Tracker tracker = currentTracker;
- if (tracker != null) {
- tracker.open(stack);
- }
- }
-
- // We keep either an allocation stack containing the closer String or, when
- // in disabled state, just the closer String.
- // We keep them in a single field only to minimize overhead.
- private Object /* String or Throwable */ closerNameOrAllocationInfo;
-
- /**
- * Marks this CloseGuard instance as closed to avoid warnings on
- * finalization.
- */
- public void close() {
- Tracker tracker = currentTracker;
- if (tracker != null && closerNameOrAllocationInfo instanceof Throwable) {
- // Invoke tracker on close only if we invoked it on open. Tracker may have changed.
- tracker.close((Throwable) closerNameOrAllocationInfo);
- }
- closerNameOrAllocationInfo = null;
- }
-
- /**
- * Logs a warning if the caller did not properly cleanup by calling an
- * explicit close method before finalization. If CloseGuard was enabled
- * when the CloseGuard was created, passes the stacktrace associated with
- * the allocation to the current reporter. If it was not enabled, it just
- * directly logs a brief message.
- */
- public void warnIfOpen() {
- if (closerNameOrAllocationInfo != null) {
- if (closerNameOrAllocationInfo instanceof String) {
- Log.w("CloseGuard", "A resource failed to call "
- + (String) closerNameOrAllocationInfo + ". ");
- } else {
- String message =
- "A resource was acquired at attached stack trace but never released. ";
- message += "See java.io.Closeable for information on avoiding resource leaks.";
- Throwable stack = (Throwable) closerNameOrAllocationInfo;
- reporter.report(message, stack);
- }
- }
- }
-
- /**
- * Interface to allow customization of tracking behaviour.
- *
- * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
- * MUST NOT be used for any other purposes.
- */
- public interface Tracker {
- void open(Throwable allocationSite);
- void close(Throwable allocationSite);
- }
-
- /**
- * Interface to allow customization of reporting behavior.
- * @hide
- */
- public interface Reporter {
- void report(String message, Throwable allocationSite);
- }
-
- /**
- * Default Reporter which reports CloseGuard violations to the log.
- */
- private static final class DefaultReporter implements Reporter {
- private DefaultReporter() {}
-
- @Override public void report (String message, Throwable allocationSite) {
- Log.w("CloseGuard", message, allocationSite);
- }
- }
-}
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 5f32c0f..f3613d3 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.audiofx.AudioEffect;
@@ -224,15 +225,16 @@
public String getClientPackageName() { return mClientPackageName; }
/**
- * @pending for SystemApi
* Returns the user id of the application performing the recording.
* <p>This information is only available if the caller has the
* {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING}
* permission.
* <br>The result is -1 without the permission.
* @return the user id
+ *
+ * @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public int getClientUid() { return mClientUid; }
/**
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 176bb37..f780d40 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -362,7 +362,8 @@
</tr>
<tr>
<td>FLAC</td>
- <td>mandatory metadata block (called the STREAMINFO block),<br>
+ <td>"fLaC", the FLAC stream marker in ASCII,<br>
+ followed by the STREAMINFO block (the mandatory metadata block),<br>
optionally followed by any number of other metadata blocks</td>
<td class=NA>Not Used</td>
<td class=NA>Not Used</td>
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 0be49d8..9100032 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -547,8 +547,6 @@
* {@link SessionCallback#onSessionCreationFailed}.
* <p>
* Pass {@code null} to sessionInfo for the failure case.
- *
- * TODO: What should router do when the session is created by manager?
*/
void createControllerOnHandler(@Nullable RouteSessionInfo sessionInfo, int requestId) {
SessionCreationRequest matchingRequest = null;
@@ -559,40 +557,44 @@
}
}
- if (matchingRequest == null) {
- Log.w(TAG, "Ignoring session creation result for unknown request."
- + " requestId=" + requestId + ", sessionInfo=" + sessionInfo);
- return;
+ if (matchingRequest != null) {
+ mSessionCreationRequests.remove(matchingRequest);
+
+ MediaRoute2Info requestedRoute = matchingRequest.mRoute;
+ String requestedControlCategory = matchingRequest.mControlCategory;
+
+ if (sessionInfo == null) {
+ // TODO: We may need to distinguish between failure and rejection.
+ // One way can be introducing 'reason'.
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!TextUtils.equals(requestedControlCategory,
+ sessionInfo.getControlCategory())) {
+ Log.w(TAG, "The session has different control category from what we requested. "
+ + "(requested=" + requestedControlCategory
+ + ", actual=" + sessionInfo.getControlCategory()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+ Log.w(TAG, "The session does not contain the requested route. "
+ + "(requestedRouteId=" + requestedRoute.getId()
+ + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ } else if (!TextUtils.equals(requestedRoute.getProviderId(),
+ sessionInfo.getProviderId())) {
+ Log.w(TAG, "The session's provider ID does not match the requested route's. "
+ + "(requested route's providerId=" + requestedRoute.getProviderId()
+ + ", actual providerId=" + sessionInfo.getProviderId()
+ + ")");
+ notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+ return;
+ }
}
- mSessionCreationRequests.remove(matchingRequest);
-
- MediaRoute2Info requestedRoute = matchingRequest.mRoute;
- String requestedControlCategory = matchingRequest.mControlCategory;
-
- if (sessionInfo == null) {
- // TODO: We may need to distinguish between failure and rejection.
- // One way can be introducing 'reason'.
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
- } else if (!TextUtils.equals(requestedControlCategory, sessionInfo.getControlCategory())) {
- Log.w(TAG, "The session has different control category from what we requested. "
- + "(requested=" + requestedControlCategory
- + ", actual=" + sessionInfo.getControlCategory()
- + ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
- } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
- Log.w(TAG, "The session does not contain the requested route. "
- + "(requestedRouteId=" + requestedRoute.getId()
- + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
- + ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
- } else if (!TextUtils.equals(requestedRoute.getProviderId(), sessionInfo.getProviderId())) {
- Log.w(TAG, "The session's provider ID does not match the requested route's. "
- + "(requested route's providerId=" + requestedRoute.getProviderId()
- + ", actual providerId=" + sessionInfo.getProviderId()
- + ")");
- notifySessionCreationFailed(requestedRoute, requestedControlCategory);
- } else {
+ if (sessionInfo != null) {
RouteSessionController controller = new RouteSessionController(sessionInfo);
mSessionControllers.put(controller.getUniqueSessionId(), controller);
notifySessionCreated(controller);
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index ef806e4..da52696 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -966,7 +966,7 @@
{ "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
{ "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
{ "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
- { "nativeCloseFilter", "()I", (void *)android_media_tv_Tuner_close_filter },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
};
static const JNINativeMethod gDescramblerMethods[] = {
@@ -975,7 +975,7 @@
{ "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
(void *)android_media_tv_Tuner_remove_pid },
{ "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
- { "nativeClose", "()V", (void *)android_media_tv_Tuner_close_descrambler },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
};
static const JNINativeMethod gDvrMethods[] = {
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 1d51c96..83c7c17 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -29,6 +29,7 @@
import android.media.MediaRoute2Info;
import android.media.MediaRouter2;
import android.media.MediaRouter2.RouteCallback;
+import android.media.MediaRouter2.SessionCallback;
import android.media.MediaRouter2Manager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -101,8 +102,8 @@
private String mPackageName;
private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>();
- private final List<RouteCallback> mRouteCallbacks =
- new ArrayList<>();
+ private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
+ private final List<SessionCallback> mSessionCallbacks = new ArrayList<>();
public static final List<String> CATEGORIES_ALL = new ArrayList();
public static final List<String> CATEGORIES_SPECIAL = new ArrayList();
@@ -205,27 +206,26 @@
}
/**
- * Tests if MR2.Callback.onRouteSelected is called when a route is selected from MR2Manager.
- *
- * TODO: Change this test so that this test check whether the route is added in a session.
- * Until then, temporailiy marking @Ignore
+ * Tests if MR2.SessionCallback.onSessionCreated is called
+ * when a route is selected from MR2Manager.
*/
@Test
- @Ignore
- public void testRouterOnRouteSelected() throws Exception {
+ public void testRouterOnSessionCreated() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
CountDownLatch latch = new CountDownLatch(1);
addManagerCallback(new MediaRouter2Manager.Callback());
-// addRouterCallback(new RouteDiscoveryCallback() {
-// @Override
-// public void onRouteSelected(MediaRoute2Info route, int reason, Bundle controlHints) {
-// if (route != null && TextUtils.equals(route.getId(), ROUTE_ID1)) {
-// latch.countDown();
-// }
-// }
-// });
+ //TODO: remove this when it's not necessary.
+ addRouterCallback(new MediaRouter2.RouteCallback());
+ addSessionCallback(new SessionCallback() {
+ @Override
+ public void onSessionCreated(MediaRouter2.RouteSessionController controller) {
+ if (createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)) {
+ latch.countDown();
+ }
+ }
+ });
MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
assertNotNull(routeToSelect);
@@ -446,6 +446,11 @@
mRouter2.registerRouteCallback(mExecutor, routeCallback);
}
+ private void addSessionCallback(SessionCallback sessionCallback) {
+ mSessionCallbacks.add(sessionCallback);
+ mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+ }
+
private void clearCallbacks() {
for (MediaRouter2Manager.Callback callback : mManagerCallbacks) {
mManager.unregisterCallback(callback);
@@ -456,5 +461,10 @@
mRouter2.unregisterRouteCallback(routeCallback);
}
mRouteCallbacks.clear();
+
+ for (SessionCallback sessionCallback : mSessionCallbacks) {
+ mRouter2.unregisterSessionCallback(sessionCallback);
+ }
+ mSessionCallbacks.clear();
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
index d79849c..4e0fd4a 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
@@ -252,6 +252,11 @@
}
@Override
+ public boolean isPluggedIn() {
+ return true;
+ }
+
+ @Override
public boolean isPowerSave() {
// Power save is not valid for the car, so always return false.
return false;
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 05de3b7..b9d65c5 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -8,7 +8,7 @@
<string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Αγγλικά (ΗΠΑ), τύπου International"</string>
<string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Αγγλικά (ΗΠΑ), τύπου Colemak"</string>
<string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Αγγλικά (ΗΠΑ), τύπου Dvorak"</string>
- <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Αγγλικά (ΗΠΑ), στυλ Workman"</string>
+ <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Αγγλικά (ΗΠΑ), στιλ Workman"</string>
<string name="keyboard_layout_german_label" msgid="8451565865467909999">"Γερμανικά"</string>
<string name="keyboard_layout_french_label" msgid="813450119589383723">"Γαλλικά"</string>
<string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Γαλλικά (Καναδά)"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index 7fc65a3..b4f5253 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -170,7 +170,7 @@
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"إيقاف"</item>
<item msgid="6014837961827347618">"الكل"</item>
- <item msgid="7387060437894578132">"الكل دون اللاسلكي"</item>
+ <item msgid="7387060437894578132">"الكل بدون اللاسلكي"</item>
<item msgid="7300881231043255746">"kernel فقط"</item>
</string-array>
<string-array name="select_logpersist_summaries">
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index d4e1b63..43d2ece 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -68,14 +68,14 @@
<string name="bluetooth_connecting" msgid="5871702668260192755">"جارٍ الاتصال…"</string>
<string name="bluetooth_connected" msgid="8065345572198502293">"الجهاز متصل<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_pairing" msgid="4269046942588193600">"جارٍ الاقتران..."</string>
- <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"الجهاز متصل (من دون هاتف)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"الجهاز متصل (من دون وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"الجهاز متصل (من دون وصول إلى الرسائل)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"الجهاز متصل (من دون هاتف أو وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"الجهاز متصل (بدون هاتف)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"الجهاز متصل (بدون وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"الجهاز متصل (بدون وصول إلى الرسائل)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"الجهاز متصل (بدون هاتف أو وسائط)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
<string name="bluetooth_connected_battery_level" msgid="5410325759372259950">"الجهاز متصل، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"الجهاز متصل (من دون هاتف)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"الجهاز متصل (من دون وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
- <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"الجهاز متّصل (من دون هاتف أو وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"الجهاز متصل (بدون هاتف)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"الجهاز متصل (بدون وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+ <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"الجهاز متّصل (بدون هاتف أو وسائط)، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level" msgid="3450745316700494425">"نشط، ومستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"مفعّلة، مستوى البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، المعدّل: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string>
<string name="bluetooth_battery_level" msgid="2893696778200201555">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 07d5ccb..3f99d10 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -227,8 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Erakutsi Bluetooth gailuak izenik gabe"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desgaitu bolumen absolutua"</string>
- <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
- <skip />
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gaitu Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Hautatu Bluetooth AVRCP bertsioa"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bluetooth bidezko audioaren kodeka"</string>
@@ -277,8 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak atzemateko"</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth gailuak izenik gabe (MAC helbideak soilik) erakutsiko dira"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Bluetooth bidezko bolumen absolutuaren eginbidea desgaitu egiten du urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu"</string>
- <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
- <skip />
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorsche eginbide sorta gaitzen du."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Tokiko terminala"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Gaitu tokiko shell-sarbidea duen terminal-aplikazioa"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"HDCP egiaztapena"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 154f386..f9ac3a5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -227,8 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"बिना नाम वाले ब्लूटूथ डिवाइस दिखाएं"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"ब्लूटूथ से आवाज़ के नियंत्रण की सुविधा रोकें"</string>
- <!-- no translation found for bluetooth_enable_gabeldorsche (9131730396242883416) -->
- <skip />
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche चालू करें"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ एवीआरसीपी वर्शन"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लूटूथ AVRCP वर्शन चुनें"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडियो कोडेक"</string>
@@ -277,8 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"नुकसानदेह व्यवहार के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जाँचें."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"बिना नाम वाले ब्लूटूथ डिवाइस (केवल MAC पते वाले) दिखाए जाएंगे"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे नियंत्रण हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के नियंत्रण की सुविधा रोक देता है."</string>
- <!-- no translation found for bluetooth_enable_gabeldorsche_summary (8472344901097607030) -->
- <skip />
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Bluetooth Gabeldorsche सुविधा का स्टैक चालू करें."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"स्थानीय टर्मिनल"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"लोकल शेल तक पहुंचने की सुविधा देने वाले टर्मिनल ऐप को चालू करें"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"एचडीसीपी जाँच"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 4c22bda..d946316 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -82,8 +82,6 @@
<item msgid="1049450003868150455">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="2908219194098827570">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="3825367753087348007">"LDAC"</item>
- <item msgid="5832677994279829983">"Omogoči izbirne kodeke"</item>
- <item msgid="9205039209798344398">"Onemogoči izbirne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="8868109554557331312">"Uporabi sistemsko izbiro (privzeto)"</item>
@@ -92,8 +90,6 @@
<item msgid="8627333814413492563">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
<item msgid="3517061573669307965">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
<item msgid="2553206901068987657">"LDAC"</item>
- <item msgid="221347164942544028">"Omogoči izbirne kodeke"</item>
- <item msgid="7416462860415701287">"Onemogoči izbirne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Uporabi sistemsko izbiro (privzeto)"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 90d7829..efd7c08 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -227,6 +227,7 @@
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Prikaži naprave Bluetooth brez imen"</string>
<string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Onemogočanje absolutne glasnosti"</string>
+ <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Omogoči Gabeldorsche"</string>
<string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Različica profila AVRCP za Bluetooth"</string>
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Izberite različico profila AVRCP za Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Zvočni kodek za Bluetooth"</string>
@@ -275,6 +276,7 @@
<string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string>
<string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazane bodo naprave Bluetooth brez imen (samo z naslovi MAC)"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogoči funkcijo absolutne glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string>
+ <string name="bluetooth_enable_gabeldorsche_summary" msgid="8472344901097607030">"Omogoči sklad funkcij Bluetooth Gabeldorche."</string>
<string name="enable_terminal_title" msgid="3834790541986303654">"Lokalni terminal"</string>
<string name="enable_terminal_summary" msgid="2481074834856064500">"Omogočanje terminalske aplikacije za dostop do lokalne lupine"</string>
<string name="hdcp_checking_title" msgid="3155692785074095986">"Preverjanje HDCP"</string>
@@ -379,7 +381,7 @@
<string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (rdeča – zelena)"</string>
<string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (modra – rumena)"</string>
<string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Popravljanje barv"</string>
- <string name="accessibility_display_daltonizer_preference_subtitle" msgid="5190814747212060815">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="9137381746633858694">"Popravljanje barv osebam z barvno slepoto pomaga, da vidijo bolj prave barve"</string>
<string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 58655a2..b4b55f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -203,13 +203,6 @@
}
}
- public int getVolume() {
- if (mService == null) {
- return 0;
- }
- return mService.getVolume();
- }
-
public void setVolume(int volume) {
if (mService == null) {
return;
@@ -224,20 +217,6 @@
return mService.getHiSyncId(device);
}
- public int getDeviceSide(BluetoothDevice device) {
- if (mService == null) {
- return BluetoothHearingAid.SIDE_LEFT;
- }
- return mService.getDeviceSide(device);
- }
-
- public int getDeviceMode(BluetoothDevice device) {
- if (mService == null) {
- return BluetoothHearingAid.MODE_MONAURAL;
- }
- return mService.getDeviceMode(device);
- }
-
public String toString() {
return NAME;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index e19ac81..6d7e86f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.text.TextUtils;
@@ -186,7 +187,8 @@
}
private static void setBatterySaverConfirmationAcknowledged(Context context) {
- Secure.putInt(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1);
+ Secure.putIntForUser(context.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1,
+ UserHandle.USER_CURRENT);
}
/**
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index 52ec1f0..0a2dd6c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -30,7 +30,7 @@
*/
@ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager {
- int VERSION = 2;
+ int VERSION = 3;
void onSucccessfulUnlock();
@@ -48,7 +48,7 @@
void setNotificationExpanded();
- boolean isClassiferEnabled();
+ boolean isClassifierEnabled();
void onQsDown();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index b960de5..35a65aa 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -26,8 +26,6 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -37,7 +35,6 @@
import android.view.WindowManager;
import android.widget.ImageView;
-import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -258,12 +255,22 @@
@Override
public void run() {
- try {
- if (DEBUG) {
- Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
- }
- final int[] result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPinReportResultForSubscriber(mSubId, mPin);
+ if (DEBUG) {
+ Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
+ }
+ TelephonyManager telephonyManager =
+ ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .createForSubscriptionId(mSubId);
+ final int[] result = telephonyManager.supplyPinReportResult(mPin);
+ if (result == null || result.length == 0) {
+ Log.e(TAG, "Error result for supplyPinReportResult.");
+ post(new Runnable() {
+ @Override
+ public void run() {
+ onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
+ }
+ });
+ } else {
if (DEBUG) {
Log.v(TAG, "supplyPinReportResult returned: " + result[0] + " " + result[1]);
}
@@ -273,14 +280,6 @@
onSimCheckResponse(result[0], result[1]);
}
});
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException for supplyPinReportResult:", e);
- post(new Runnable() {
- @Override
- public void run() {
- onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
- }
- });
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 7e08ab3..dc68115 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -25,8 +25,6 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -36,7 +34,6 @@
import android.view.WindowManager;
import android.widget.ImageView;
-import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -318,10 +315,20 @@
@Override
public void run() {
- try {
- if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
- final int[] result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPukReportResultForSubscriber(mSubId, mPuk, mPin);
+ if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
+ TelephonyManager telephonyManager =
+ ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
+ .createForSubscriptionId(mSubId);
+ final int[] result = telephonyManager.supplyPukReportResult(mPuk, mPin);
+ if (result == null || result.length == 0) {
+ Log.e(TAG, "Error result for supplyPukReportResult.");
+ post(new Runnable() {
+ @Override
+ public void run() {
+ onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
+ }
+ });
+ } else {
if (DEBUG) {
Log.v(TAG, "supplyPukReportResult returned: " + result[0] + " " + result[1]);
}
@@ -331,14 +338,6 @@
onSimLockChangedResponse(result[0], result[1]);
}
});
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException for supplyPukReportResult:", e);
- post(new Runnable() {
- @Override
- public void run() {
- onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1);
- }
- });
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 4728327..02a4521 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -694,7 +694,7 @@
public boolean isFalseGesture(MotionEvent ev) {
boolean falsingDetected = mCallback.isAntiFalsingNeeded();
- if (mFalsingManager.isClassiferEnabled()) {
+ if (mFalsingManager.isClassifierEnabled()) {
falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
} else {
falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 995b35f..fdeaf1f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -134,7 +134,8 @@
if (isStack) {
mViewPositionOnTouchDown.set(mStack.getStackPosition());
mStack.onDragStart();
- if (!mStack.isShowingBubbleMenu() && !mStack.isExpanded()) {
+ if (!mStack.isShowingBubbleMenu() && !mStack.isExpanded()
+ && BubbleExperimentConfig.allowBubbleScreenshotMenu(mContext)) {
mShowBubbleMenuRunnable = mStack::showBubbleMenu;
mStack.postDelayed(mShowBubbleMenuRunnable,
ViewConfiguration.getLongPressTimeout());
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index ea175ed..099909d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -90,7 +90,7 @@
}
@Override
- public boolean isClassiferEnabled() {
+ public boolean isClassifierEnabled() {
return mIsClassiferEnabled;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index eb014ed..d6faed5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -213,7 +213,7 @@
private void onSessionStart() {
if (FalsingLog.ENABLED) {
- FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassiferEnabled());
+ FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassifierEnabled());
clearPendingWtf();
}
mBouncerOn = false;
@@ -246,7 +246,7 @@
}
}
- public boolean isClassiferEnabled() {
+ public boolean isClassifierEnabled() {
return mHumanInteractionClassifier.isEnabled();
}
@@ -544,7 +544,7 @@
public void dump(PrintWriter pw) {
pw.println("FALSING MANAGER");
- pw.print("classifierEnabled="); pw.println(isClassiferEnabled() ? 1 : 0);
+ pw.print("classifierEnabled="); pw.println(isClassifierEnabled() ? 1 : 0);
pw.print("mSessionActive="); pw.println(mSessionActive ? 1 : 0);
pw.print("mBouncerOn="); pw.println(mSessionActive ? 1 : 0);
pw.print("mState="); pw.println(StatusBarState.toShortString(mState));
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index f475948..b2131e7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -21,8 +21,8 @@
import android.content.Context;
import android.hardware.SensorManager;
import android.net.Uri;
-import android.os.Handler;
import android.provider.DeviceConfig;
+import android.util.DisplayMetrics;
import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
@@ -32,6 +32,7 @@
import com.android.systemui.classifier.brightline.FalsingDataProvider;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
@@ -56,19 +57,22 @@
private static final String PROXIMITY_SENSOR_TAG = "FalsingManager";
private final ProximitySensor mProximitySensor;
+ private final DisplayMetrics mDisplayMetrics;
private FalsingManager mInternalFalsingManager;
private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener;
private final DeviceConfigProxy mDeviceConfig;
private boolean mBrightlineEnabled;
+ private final DockManager mDockManager;
private Executor mUiBgExecutor;
@Inject
- FalsingManagerProxy(Context context, PluginManager pluginManager,
- @Main Handler handler,
- ProximitySensor proximitySensor,
- DeviceConfigProxy deviceConfig,
+ FalsingManagerProxy(Context context, PluginManager pluginManager, @Main Executor executor,
+ DisplayMetrics displayMetrics, ProximitySensor proximitySensor,
+ DeviceConfigProxy deviceConfig, DockManager dockManager,
@UiBackground Executor uiBgExecutor) {
+ mDisplayMetrics = displayMetrics;
mProximitySensor = proximitySensor;
+ mDockManager = dockManager;
mUiBgExecutor = uiBgExecutor;
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME);
@@ -78,7 +82,7 @@
setupFalsingManager(context);
mDeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI,
- handler::post,
+ executor,
mDeviceConfigListener
);
@@ -125,10 +129,11 @@
mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
- new FalsingDataProvider(context.getResources().getDisplayMetrics()),
+ new FalsingDataProvider(mDisplayMetrics),
Dependency.get(KeyguardUpdateMonitor.class),
mProximitySensor,
- mDeviceConfig
+ mDeviceConfig,
+ mDockManager
);
}
}
@@ -182,8 +187,8 @@
}
@Override
- public boolean isClassiferEnabled() {
- return mInternalFalsingManager.isClassiferEnabled();
+ public boolean isClassifierEnabled() {
+ return mInternalFalsingManager.isClassifierEnabled();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index bd0906a..b2e61a2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -25,17 +25,21 @@
import android.view.MotionEvent;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.classifier.Classifier;
+import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.ProximitySensor;
import java.io.PrintWriter;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.Queue;
/**
* FalsingManager designed to make clear why a touch was rejected.
@@ -44,16 +48,20 @@
static final boolean DEBUG = false;
private static final String TAG = "FalsingManager";
+ private static final int RECENT_INFO_LOG_SIZE = 20;
private final FalsingDataProvider mDataProvider;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final ProximitySensor mProximitySensor;
+ private final DockManager mDockManager;
private boolean mSessionStarted;
private MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
private boolean mShowingAod;
private boolean mScreenOn;
private boolean mJustUnlockedWithFace;
+ private static final Queue<String> RECENT_INFO_LOG =
+ new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1);
private final List<FalsingClassifier> mClassifiers;
@@ -71,14 +79,14 @@
}
};
- public BrightLineFalsingManager(
- FalsingDataProvider falsingDataProvider,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- ProximitySensor proximitySensor,
- DeviceConfigProxy deviceConfigProxy) {
+ public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
+ KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor,
+ DeviceConfigProxy deviceConfigProxy,
+ DockManager dockManager) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDataProvider = falsingDataProvider;
mProximitySensor = proximitySensor;
+ mDockManager = dockManager;
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
mMetricsLogger = new MetricsLogger();
@@ -134,29 +142,30 @@
}
@Override
- public boolean isClassiferEnabled() {
+ public boolean isClassifierEnabled() {
return true;
}
@Override
public boolean isFalseTouch() {
- boolean r = !mJustUnlockedWithFace && mClassifiers.stream().anyMatch(falsingClassifier -> {
- boolean result = falsingClassifier.isFalseTouch();
- if (result) {
- logInfo(String.format(
- (Locale) null,
- "{classifier=%s, interactionType=%d}",
- falsingClassifier.getClass().getName(),
- mDataProvider.getInteractionType()));
- String reason = falsingClassifier.getReason();
- if (reason != null) {
- logInfo(reason);
- }
- } else {
- logDebug(falsingClassifier.getClass().getName() + ": false");
- }
- return result;
- });
+ boolean r = !mJustUnlockedWithFace && !mDockManager.isDocked()
+ && mClassifiers.stream().anyMatch(falsingClassifier -> {
+ boolean result = falsingClassifier.isFalseTouch();
+ if (result) {
+ logInfo(String.format(
+ (Locale) null,
+ "{classifier=%s, interactionType=%d}",
+ falsingClassifier.getClass().getName(),
+ mDataProvider.getInteractionType()));
+ String reason = falsingClassifier.getReason();
+ if (reason != null) {
+ logInfo(reason);
+ }
+ } else {
+ logDebug(falsingClassifier.getClass().getName() + ": false");
+ }
+ return result;
+ });
logDebug("Is false touch? " + r);
@@ -336,7 +345,18 @@
}
@Override
- public void dump(PrintWriter printWriter) {
+ public void dump(PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println("BRIGHTLINE FALSING MANAGER");
+ ipw.print("classifierEnabled="); pw.println(isClassifierEnabled() ? 1 : 0);
+ ipw.print("mJustUnlockedWithFace="); pw.println(mJustUnlockedWithFace ? 1 : 0);
+ ipw.print("isDocked="); pw.println(mDockManager.isDocked() ? 1 : 0);
+ ipw.println();
+ ipw.println("Recent falsing info:");
+ ipw.increaseIndent();
+ for (String msg : RECENT_INFO_LOG) {
+ ipw.println(msg);
+ }
}
@Override
@@ -357,6 +377,10 @@
static void logInfo(String msg) {
Log.i(TAG, msg);
+ RECENT_INFO_LOG.add(msg);
+ while (RECENT_INFO_LOG.size() > RECENT_INFO_LOG_SIZE) {
+ RECENT_INFO_LOG.remove();
+ }
}
static void logError(String msg) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index eb19571..c8cf02a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -585,10 +585,10 @@
resolver,
Global.LOW_POWER_MODE_TRIGGER_LEVEL,
batterySaverTriggerLevel);
- Secure.putInt(
+ Secure.putIntForUser(
resolver,
Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
- 1);
+ 1, UserHandle.USER_CURRENT);
});
} else {
d.setTitle(R.string.battery_saver_confirmation_title);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 9261412..bbff117 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -42,6 +42,7 @@
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Manages the lifecycle of a TileService.
@@ -84,7 +85,8 @@
private int mBindTryCount;
private int mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
private boolean mBound;
- boolean mReceiverRegistered;
+ private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
+ private AtomicBoolean mUserReceiverRegistered = new AtomicBoolean(false);
private boolean mUnbindImmediate;
private TileChangeListener mChangeListener;
// Return value from bindServiceAsUser, determines whether safe to call unbind.
@@ -274,7 +276,7 @@
public void handleDestroy() {
if (DEBUG) Log.d(TAG, "handleDestroy");
- if (mReceiverRegistered) {
+ if (mPackageReceiverRegistered.get() || mUserReceiverRegistered.get()) {
stopPackageListening();
}
}
@@ -310,17 +312,31 @@
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
- mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ try {
+ mPackageReceiverRegistered.set(true);
+ mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ } catch (Exception ex) {
+ mPackageReceiverRegistered.set(false);
+ Log.e(TAG, "Could not register package receiver", ex);
+ }
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
- mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
- mReceiverRegistered = true;
+ try {
+ mUserReceiverRegistered.set(true);
+ mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
+ } catch (Exception ex) {
+ mUserReceiverRegistered.set(false);
+ Log.e(TAG, "Could not register unlock receiver", ex);
+ }
}
private void stopPackageListening() {
if (DEBUG) Log.d(TAG, "stopPackageListening");
- mContext.unregisterReceiver(this);
- mBroadcastDispatcher.unregisterReceiver(this);
- mReceiverRegistered = false;
+ if (mUserReceiverRegistered.compareAndSet(true, false)) {
+ mBroadcastDispatcher.unregisterReceiver(this);
+ }
+ if (mPackageReceiverRegistered.compareAndSet(true, false)) {
+ mContext.unregisterReceiver(this);
+ }
}
public void setTileChangeListener(TileChangeListener changeListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 9a33c8c..f06c849 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -38,7 +38,6 @@
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
@@ -182,8 +181,7 @@
return mUiModeNightTileProvider.get();
}
- // Intent tiles.
- if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
+ // Custom tiles
if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
// Debug tiles.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
deleted file mode 100644
index a639a95..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-public class IntentTile extends QSTileImpl<State> {
- public static final String PREFIX = "intent(";
-
- private PendingIntent mOnClick;
- private String mOnClickUri;
- private PendingIntent mOnLongClick;
- private String mOnLongClickUri;
- private int mCurrentUserId;
- private String mIntentPackage;
-
- private Intent mLastIntent;
-
- private IntentTile(QSHost host, String action) {
- super(host);
- mContext.registerReceiver(mReceiver, new IntentFilter(action));
- }
-
- @Override
- protected void handleDestroy() {
- super.handleDestroy();
- mContext.unregisterReceiver(mReceiver);
- }
-
- public static IntentTile create(QSHost host, String spec) {
- if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
- throw new IllegalArgumentException("Bad intent tile spec: " + spec);
- }
- final String action = spec.substring(PREFIX.length(), spec.length() - 1);
- if (action.isEmpty()) {
- throw new IllegalArgumentException("Empty intent tile spec action");
- }
- return new IntentTile(host, action);
- }
-
- @Override
- public void handleSetListening(boolean listening) {
- }
-
- @Override
- public State newTileState() {
- return new State();
- }
-
- @Override
- protected void handleUserSwitch(int newUserId) {
- super.handleUserSwitch(newUserId);
- mCurrentUserId = newUserId;
- }
-
- @Override
- protected void handleClick() {
- sendIntent("click", mOnClick, mOnClickUri);
- }
-
- @Override
- public Intent getLongClickIntent() {
- return null;
- }
-
- @Override
- protected void handleLongClick() {
- sendIntent("long-click", mOnLongClick, mOnLongClickUri);
- }
-
- private void sendIntent(String type, PendingIntent pi, String uri) {
- try {
- if (pi != null) {
- if (pi.isActivity()) {
- Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(pi);
- } else {
- pi.send();
- }
- } else if (uri != null) {
- final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
- mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
- }
- } catch (Throwable t) {
- Log.w(TAG, "Error sending " + type + " intent", t);
- }
- }
-
- @Override
- public CharSequence getTileLabel() {
- return getState().label;
- }
-
- @Override
- protected void handleUpdateState(State state, Object arg) {
- Intent intent = (Intent) arg;
- if (intent == null) {
- if (mLastIntent == null) {
- return;
- }
- // No intent but need to refresh state, just use the last one.
- intent = mLastIntent;
- }
- // Save the last one in case we need it later.
- mLastIntent = intent;
- state.contentDescription = intent.getStringExtra("contentDescription");
- state.label = intent.getStringExtra("label");
- state.icon = null;
- final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
- if (iconBitmap != null) {
- try {
- state.icon = new BytesIcon(iconBitmap);
- } catch (Throwable t) {
- Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
- }
- } else {
- final int iconId = intent.getIntExtra("iconId", 0);
- if (iconId != 0) {
- final String iconPackage = intent.getStringExtra("iconPackage");
- if (!TextUtils.isEmpty(iconPackage)) {
- state.icon = new PackageDrawableIcon(iconPackage, iconId);
- } else {
- state.icon = ResourceIcon.get(iconId);
- }
- }
- }
- mOnClick = intent.getParcelableExtra("onClick");
- mOnClickUri = intent.getStringExtra("onClickUri");
- mOnLongClick = intent.getParcelableExtra("onLongClick");
- mOnLongClickUri = intent.getStringExtra("onLongClickUri");
- mIntentPackage = intent.getStringExtra("package");
- mIntentPackage = mIntentPackage == null ? "" : mIntentPackage;
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_INTENT;
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- refreshState(intent);
- }
- };
-
- private static class BytesIcon extends Icon {
- private final byte[] mBytes;
-
- public BytesIcon(byte[] bytes) {
- mBytes = bytes;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
- return new BitmapDrawable(context.getResources(), b);
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
- }
-
- @Override
- public String toString() {
- return String.format("BytesIcon[len=%s]", mBytes.length);
- }
- }
-
- private class PackageDrawableIcon extends Icon {
- private final String mPackage;
- private final int mResId;
-
- public PackageDrawableIcon(String pkg, int resId) {
- mPackage = pkg;
- mResId = resId;
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof PackageDrawableIcon)) return false;
- final PackageDrawableIcon other = (PackageDrawableIcon) o;
- return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- try {
- return context.createPackageContext(mPackage, 0).getDrawable(mResId);
- } catch (Throwable t) {
- Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
- return null;
- }
- }
-
- @Override
- public String toString() {
- return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index d3ccbeb..77c3ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -27,7 +27,6 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -42,6 +41,7 @@
import android.util.Log;
import android.util.Size;
import android.view.Surface;
+import android.view.WindowManager;
import android.widget.Toast;
import com.android.systemui.R;
@@ -76,7 +76,7 @@
private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private static final int TOTAL_NUM_TRACKS = 1;
- private static final int VIDEO_BIT_RATE = 6000000;
+ private static final int VIDEO_BIT_RATE = 10000000;
private static final int VIDEO_FRAME_RATE = 30;
private static final int AUDIO_BIT_RATE = 16;
private static final int AUDIO_SAMPLE_RATE = 44100;
@@ -238,7 +238,9 @@
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// Set up video
- DisplayMetrics metrics = getResources().getDisplayMetrics();
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getRealMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 8dd801b..8cc45f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -51,7 +51,7 @@
private final Context mContext;
private final NotificationManager mNotificationManager;
private final Handler mMainHandler;
- private final List<NotifServiceListener> mNotificationListeners = new ArrayList<>();
+ private final List<NotificationHandler> mNotificationHandlers = new ArrayList<>();
private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
@Inject
@@ -65,11 +65,11 @@
}
/** Registers a listener that's notified when notifications are added/removed/etc. */
- public void addNotificationListener(NotifServiceListener listener) {
- if (mNotificationListeners.contains(listener)) {
+ public void addNotificationHandler(NotificationHandler handler) {
+ if (mNotificationHandlers.contains(handler)) {
throw new IllegalArgumentException("Listener is already added");
}
- mNotificationListeners.add(listener);
+ mNotificationHandlers.add(handler);
}
/** Registers a listener that's notified when any notification-related settings change. */
@@ -100,7 +100,7 @@
final RankingMap completeMap = new RankingMap(newRankings.toArray(new Ranking[0]));
for (StatusBarNotification sbn : notifications) {
- for (NotifServiceListener listener : mNotificationListeners) {
+ for (NotificationHandler listener : mNotificationHandlers) {
listener.onNotificationPosted(sbn, completeMap);
}
}
@@ -117,8 +117,8 @@
mMainHandler.post(() -> {
processForRemoteInput(sbn.getNotification(), mContext);
- for (NotifServiceListener listener : mNotificationListeners) {
- listener.onNotificationPosted(sbn, rankingMap);
+ for (NotificationHandler handler : mNotificationHandlers) {
+ handler.onNotificationPosted(sbn, rankingMap);
}
});
}
@@ -130,8 +130,8 @@
if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason);
if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
mMainHandler.post(() -> {
- for (NotifServiceListener listener : mNotificationListeners) {
- listener.onNotificationRemoved(sbn, rankingMap, reason);
+ for (NotificationHandler handler : mNotificationHandlers) {
+ handler.onNotificationRemoved(sbn, rankingMap, reason);
}
});
}
@@ -148,8 +148,8 @@
if (rankingMap != null) {
RankingMap r = onPluginRankingUpdate(rankingMap);
mMainHandler.post(() -> {
- for (NotifServiceListener listener : mNotificationListeners) {
- listener.onNotificationRankingUpdate(r);
+ for (NotificationHandler handler : mNotificationHandlers) {
+ handler.onNotificationRankingUpdate(r);
}
});
}
@@ -207,7 +207,7 @@
}
/** Interface for listening to add/remove events that we receive from NotificationManager. */
- public interface NotifServiceListener {
+ public interface NotificationHandler {
void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap);
void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap);
void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, int reason);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 778443c..fdb793e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -33,6 +33,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Keeps track of the currently active {@link RemoteInputView}s.
@@ -108,8 +109,8 @@
* @param token a token identifying the view that is managing the remote input
*/
public void addRemoteInput(NotificationEntry entry, Object token) {
- Preconditions.checkNotNull(entry);
- Preconditions.checkNotNull(token);
+ Objects.requireNonNull(entry);
+ Objects.requireNonNull(token);
boolean found = pruneWeakThenRemoveAndContains(
entry /* contains */, null /* remove */, token /* removeToken */);
@@ -129,7 +130,7 @@
* entry. If null, the entry is removed regardless.
*/
public void removeRemoteInput(NotificationEntry entry, Object token) {
- Preconditions.checkNotNull(entry);
+ Objects.requireNonNull(entry);
pruneWeakThenRemoveAndContains(null /* contains */, entry /* remove */, token);
@@ -143,8 +144,8 @@
* @param token the token of the view managing the remote input.
*/
public void addSpinning(String key, Object token) {
- Preconditions.checkNotNull(key);
- Preconditions.checkNotNull(token);
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(token);
mSpinning.put(key, token);
}
@@ -158,7 +159,7 @@
* entry. If null, the entry is removed regardless.
*/
public void removeSpinning(String key, Object token) {
- Preconditions.checkNotNull(key);
+ Objects.requireNonNull(key);
if (token == null || mSpinning.get(key) == token) {
mSpinning.remove(key);
@@ -237,7 +238,7 @@
public void addCallback(Callback callback) {
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
mCallbacks.add(callback);
}
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 b8afb78..33d97a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -36,7 +36,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
@@ -179,7 +179,7 @@
/** Once called, the NEM will start processing notification events from system server. */
public void attach(NotificationListener notificationListener) {
- notificationListener.addNotificationListener(mNotifListener);
+ notificationListener.addNotificationHandler(mNotifListener);
}
/** Adds a {@link NotificationEntryListener}. */
@@ -326,7 +326,7 @@
}
}
- private final NotifServiceListener mNotifListener = new NotifServiceListener() {
+ private final NotificationHandler mNotifListener = new NotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
final boolean isUpdate = mActiveNotifications.containsKey(sbn.getKey());
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 7b1dc07..f2765db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -16,14 +16,14 @@
package com.android.systemui.statusbar.notification;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+import java.util.Objects;
+
/**
* Root controller for the list of notifications in the shade.
*
@@ -39,9 +39,9 @@
NotificationEntryManager entryManager,
NotificationListContainer listContainer,
DeviceProvisionedController deviceProvisionedController) {
- mEntryManager = checkNotNull(entryManager);
- mListContainer = checkNotNull(listContainer);
- mDeviceProvisionedController = checkNotNull(deviceProvisionedController);
+ mEntryManager = Objects.requireNonNull(entryManager);
+ mListContainer = Objects.requireNonNull(listContainer);
+ mDeviceProvisionedController = Objects.requireNonNull(deviceProvisionedController);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
index cefb506..87aaea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
@@ -24,18 +24,6 @@
*/
public interface CollectionReadyForBuildListener {
/**
- * Called after the NotifCollection has received an update from NotificationManager but before
- * it dispatches any change events to its listeners. This is to inform the list builder that
- * the first stage of the pipeline has been triggered. After events have been dispatched,
- * onBuildList() will be called.
- *
- * While onBuildList() is always called after this method is called, the converse is not always
- * true: sometimes the NotifCollection applies an update that does not need to dispatch events,
- * in which case this method will be skipped and onBuildList will be called directly.
- */
- void onBeginDispatchToListeners();
-
- /**
* Called by the NotifCollection to indicate that something in the collection has changed and
* that the list builder should regenerate the list.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 7f85c88..873cdbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -35,8 +35,6 @@
import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
@@ -49,8 +47,9 @@
import android.util.Log;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
import com.android.systemui.util.Assert;
import java.lang.annotation.Retention;
@@ -60,6 +59,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -109,14 +109,14 @@
}
/** Initializes the NotifCollection and registers it to receive notification events. */
- public void attach(NotificationListener listenerService) {
+ public void attach(GroupCoalescer groupCoalescer) {
Assert.isMainThread();
if (mAttached) {
throw new RuntimeException("attach() called twice");
}
mAttached = true;
- listenerService.addNotificationListener(mNotifServiceListener);
+ groupCoalescer.setNotificationHandler(mNotifHandler);
}
/**
@@ -170,7 +170,7 @@
@CancellationReason int reason,
@NonNull DismissedByUserStats stats) {
Assert.isMainThread();
- checkNotNull(stats);
+ Objects.requireNonNull(stats);
checkForReentrantCall();
removeNotification(entry.getKey(), null, reason, stats);
@@ -179,15 +179,52 @@
private void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
Assert.isMainThread();
+ postNotification(sbn, requireRanking(rankingMap, sbn.getKey()), rankingMap);
+ rebuildList();
+ }
+
+ private void onNotificationGroupPosted(List<CoalescedEvent> batch) {
+ Assert.isMainThread();
+
+ Log.d(TAG, "POSTED GROUP " + batch.get(0).getSbn().getGroupKey()
+ + " (" + batch.size() + " events)");
+ for (CoalescedEvent event : batch) {
+ postNotification(event.getSbn(), event.getRanking(), null);
+ }
+ rebuildList();
+ }
+
+ private void onNotificationRemoved(
+ StatusBarNotification sbn,
+ RankingMap rankingMap,
+ int reason) {
+ Assert.isMainThread();
+
+ Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+ removeNotification(sbn.getKey(), rankingMap, reason, null);
+ }
+
+ private void onNotificationRankingUpdate(RankingMap rankingMap) {
+ Assert.isMainThread();
+ applyRanking(rankingMap);
+ rebuildList();
+ }
+
+ private void postNotification(
+ StatusBarNotification sbn,
+ Ranking ranking,
+ @Nullable RankingMap rankingMap) {
NotificationEntry entry = mNotificationSet.get(sbn.getKey());
if (entry == null) {
// A new notification!
Log.d(TAG, "POSTED " + sbn.getKey());
- entry = new NotificationEntry(sbn, requireRanking(rankingMap, sbn.getKey()));
+ entry = new NotificationEntry(sbn, ranking);
mNotificationSet.put(sbn.getKey(), entry);
- applyRanking(rankingMap);
+ if (rankingMap != null) {
+ applyRanking(rankingMap);
+ }
dispatchOnEntryAdded(entry);
@@ -200,34 +237,19 @@
cancelLifetimeExtension(entry);
entry.setSbn(sbn);
- applyRanking(rankingMap);
+ if (rankingMap != null) {
+ applyRanking(rankingMap);
+ }
dispatchOnEntryUpdated(entry);
}
-
- rebuildList();
- }
-
- private void onNotificationRemoved(
- StatusBarNotification sbn,
- @Nullable RankingMap rankingMap,
- int reason) {
- Assert.isMainThread();
- Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
- removeNotification(sbn.getKey(), rankingMap, reason, null);
- }
-
- private void onNotificationRankingUpdate(RankingMap rankingMap) {
- Assert.isMainThread();
- applyRanking(rankingMap);
- rebuildList();
}
private void removeNotification(
String key,
@Nullable RankingMap rankingMap,
@CancellationReason int reason,
- DismissedByUserStats dismissedByUserStats) {
+ @Nullable DismissedByUserStats dismissedByUserStats) {
NotificationEntry entry = mNotificationSet.get(key);
if (entry == null) {
@@ -272,7 +294,7 @@
rebuildList();
}
- private void applyRanking(RankingMap rankingMap) {
+ private void applyRanking(@NonNull RankingMap rankingMap) {
for (NotificationEntry entry : mNotificationSet.values()) {
if (!isLifetimeExtended(entry)) {
Ranking ranking = requireRanking(rankingMap, entry.getKey());
@@ -339,9 +361,6 @@
private void dispatchOnEntryAdded(NotificationEntry entry) {
mAmDispatchingToOtherCode = true;
- if (mBuildListener != null) {
- mBuildListener.onBeginDispatchToListeners();
- }
for (NotifCollectionListener listener : mNotifCollectionListeners) {
listener.onEntryAdded(entry);
}
@@ -350,9 +369,6 @@
private void dispatchOnEntryUpdated(NotificationEntry entry) {
mAmDispatchingToOtherCode = true;
- if (mBuildListener != null) {
- mBuildListener.onBeginDispatchToListeners();
- }
for (NotifCollectionListener listener : mNotifCollectionListeners) {
listener.onEntryUpdated(entry);
}
@@ -364,22 +380,24 @@
@CancellationReason int reason,
boolean removedByUser) {
mAmDispatchingToOtherCode = true;
- if (mBuildListener != null) {
- mBuildListener.onBeginDispatchToListeners();
- }
for (NotifCollectionListener listener : mNotifCollectionListeners) {
listener.onEntryRemoved(entry, reason, removedByUser);
}
mAmDispatchingToOtherCode = false;
}
- private final NotifServiceListener mNotifServiceListener = new NotifServiceListener() {
+ private final BatchableNotificationHandler mNotifHandler = new BatchableNotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
NotifCollection.this.onNotificationPosted(sbn, rankingMap);
}
@Override
+ public void onNotificationBatchPosted(List<CoalescedEvent> events) {
+ NotifCollection.this.onNotificationGroupPosted(events);
+ }
+
+ @Override
public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
NotifCollection.this.onNotificationRemoved(sbn, rankingMap, REASON_UNKNOWN);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
index f0a003f..19d90f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
@@ -18,7 +18,6 @@
import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpList;
-import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_PENDING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING;
import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING;
@@ -198,12 +197,6 @@
private final CollectionReadyForBuildListener mReadyForBuildListener =
new CollectionReadyForBuildListener() {
@Override
- public void onBeginDispatchToListeners() {
- Assert.isMainThread();
- mPipelineState.incrementTo(STATE_BUILD_PENDING);
- }
-
- @Override
public void onBuildList(Collection<NotificationEntry> entries) {
Assert.isMainThread();
mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index dd3a3e0..4f4fb24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -29,7 +29,6 @@
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
import android.annotation.NonNull;
@@ -162,9 +161,9 @@
public NotificationEntry(
@NonNull StatusBarNotification sbn,
@NonNull Ranking ranking) {
- super(checkNotNull(checkNotNull(sbn).getKey()));
+ super(Objects.requireNonNull(Objects.requireNonNull(sbn).getKey()));
- checkNotNull(ranking);
+ Objects.requireNonNull(ranking);
mKey = sbn.getKey();
setSbn(sbn);
@@ -194,8 +193,8 @@
* TODO: Make this package-private
*/
public void setSbn(@NonNull StatusBarNotification sbn) {
- checkNotNull(sbn);
- checkNotNull(sbn.getKey());
+ Objects.requireNonNull(sbn);
+ Objects.requireNonNull(sbn.getKey());
if (!sbn.getKey().equals(mKey)) {
throw new IllegalArgumentException("New key " + sbn.getKey()
@@ -223,8 +222,8 @@
* TODO: Make this package-private
*/
public void setRanking(@NonNull Ranking ranking) {
- checkNotNull(ranking);
- checkNotNull(ranking.getKey());
+ Objects.requireNonNull(ranking);
+ Objects.requireNonNull(ranking.getKey());
if (!ranking.getKey().equals(mKey)) {
throw new IllegalArgumentException("New key " + ranking.getKey()
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 8afbc27..6c93618 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
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.collection;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
@@ -51,6 +50,8 @@
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import java.util.Objects;
+
/** Handles inflating and updating views for notifications. */
public class NotificationRowBinderImpl implements NotificationRowBinder {
@@ -265,7 +266,7 @@
row.inflateViews();
// bind the click event to the content area
- checkNotNull(mNotificationClicker).register(row, sbn);
+ Objects.requireNonNull(mNotificationClicker).register(row, sbn);
}
private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
index 5fc55da..5e0bd4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
@@ -24,6 +24,7 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -36,6 +37,7 @@
*/
@Singleton
public class NewNotifPipeline implements Dumpable {
+ private final GroupCoalescer mGroupCoalescer;
private final NotifCollection mNotifCollection;
private final NotifListBuilderImpl mNotifPipeline;
private final NotifCoordinators mNotifPluggableCoordinators;
@@ -45,10 +47,12 @@
@Inject
public NewNotifPipeline(
+ GroupCoalescer groupCoalescer,
NotifCollection notifCollection,
NotifListBuilderImpl notifPipeline,
NotifCoordinators notifCoordinators,
DumpController dumpController) {
+ mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
mNotifPipeline = notifPipeline;
mNotifPluggableCoordinators = notifCoordinators;
@@ -58,20 +62,26 @@
/** Hooks the new pipeline up to NotificationManager */
public void initialize(
NotificationListener notificationService) {
- mFakePipelineConsumer.attach(mNotifPipeline);
- mNotifPipeline.attach(mNotifCollection);
- mNotifCollection.attach(notificationService);
- mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
-
- Log.d(TAG, "Notif pipeline initialized");
mDumpController.registerDumpable("NotifPipeline", this);
+
+ // Wire up coordinators
+ mFakePipelineConsumer.attach(mNotifPipeline);
+ mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
+
+ // Wire up pipeline
+ mNotifPipeline.attach(mNotifCollection);
+ mNotifCollection.attach(mGroupCoalescer);
+ mGroupCoalescer.attach(notificationService);
+
+ Log.d(TAG, "Notif pipeline initialized");
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mFakePipelineConsumer.dump(fd, pw, args);
mNotifPluggableCoordinators.dump(fd, pw, args);
+ mGroupCoalescer.dump(fd, pw, args);
}
private static final String TAG = "NewNotifPipeline";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
index 85f828d..084d038 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
@@ -76,19 +76,17 @@
}
public static final int STATE_IDLE = 0;
- public static final int STATE_BUILD_PENDING = 1;
- public static final int STATE_BUILD_STARTED = 2;
- public static final int STATE_RESETTING = 3;
- public static final int STATE_PRE_GROUP_FILTERING = 4;
- public static final int STATE_GROUPING = 5;
- public static final int STATE_TRANSFORMING = 6;
- public static final int STATE_SORTING = 7;
- public static final int STATE_PRE_RENDER_FILTERING = 8;
- public static final int STATE_FINALIZING = 9;
+ public static final int STATE_BUILD_STARTED = 1;
+ public static final int STATE_RESETTING = 2;
+ public static final int STATE_PRE_GROUP_FILTERING = 3;
+ public static final int STATE_GROUPING = 4;
+ public static final int STATE_TRANSFORMING = 5;
+ public static final int STATE_SORTING = 6;
+ public static final int STATE_PRE_RENDER_FILTERING = 7;
+ public static final int STATE_FINALIZING = 8;
@IntDef(prefix = { "STATE_" }, value = {
STATE_IDLE,
- STATE_BUILD_PENDING,
STATE_BUILD_STARTED,
STATE_RESETTING,
STATE_PRE_GROUP_FILTERING,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt
new file mode 100644
index 0000000..b6218b4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.service.notification.NotificationListenerService.Ranking
+import android.service.notification.StatusBarNotification
+
+data class CoalescedEvent(
+ val key: String,
+ var position: Int,
+ var sbn: StatusBarNotification,
+ var ranking: Ranking,
+ var batch: EventBatch?
+) {
+ override fun toString(): String {
+ return "CoalescedEvent(key=$key)"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java
new file mode 100644
index 0000000..ac51178
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a set of notification post events for a particular notification group.
+ */
+public class EventBatch {
+ /** SystemClock.uptimeMillis() */
+ final long mCreatedTimestamp;
+
+ /** SBN.getGroupKey -- same for all members */
+ final String mGroupKey;
+
+ /**
+ * All members of the batch. Must share the same group key. Includes both children and
+ * summaries.
+ */
+ final List<CoalescedEvent> mMembers = new ArrayList<>();
+
+ EventBatch(long createdTimestamp, String groupKey) {
+ mCreatedTimestamp = createdTimestamp;
+ this.mGroupKey = groupKey;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java
new file mode 100644
index 0000000..069c15f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+
+import static com.android.systemui.statusbar.notification.logging.NotifEvent.COALESCED_EVENT;
+import static com.android.systemui.statusbar.notification.logging.NotifEvent.EARLY_BATCH_EMIT;
+import static com.android.systemui.statusbar.notification.logging.NotifEvent.EMIT_EVENT_BATCH;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.MainThread;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.SystemClock;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+/**
+ * An attempt to make posting notification groups an atomic process
+ *
+ * Due to the nature of the groups API, individual members of a group are posted to system server
+ * one at a time. This means that whenever a group member is posted, we don't know if there are any
+ * more members soon to be posted.
+ *
+ * The Coalescer sits between the NotificationListenerService and the NotifCollection. It clusters
+ * new notifications that are members of groups and delays their posting until any of the following
+ * criteria are met:
+ *
+ * - A few milliseconds pass (see groupLingerDuration on the constructor)
+ * - Any notification in the delayed group is updated
+ * - Any notification in the delayed group is retracted
+ *
+ * Once we cross this threshold, all members of the group in question are posted atomically to the
+ * NotifCollection. If this process was triggered by an update or removal, then that event is then
+ * passed along to the NotifCollection.
+ */
+@MainThread
+public class GroupCoalescer implements Dumpable {
+ private final DelayableExecutor mMainExecutor;
+ private final SystemClock mClock;
+ private final NotifLog mLog;
+ private final long mGroupLingerDuration;
+
+ private BatchableNotificationHandler mHandler;
+
+ private final Map<String, CoalescedEvent> mCoalescedEvents = new ArrayMap<>();
+ private final Map<String, EventBatch> mBatches = new ArrayMap<>();
+
+ @Inject
+ public GroupCoalescer(
+ @Main DelayableExecutor mainExecutor,
+ SystemClock clock, NotifLog log) {
+ this(mainExecutor, clock, log, GROUP_LINGER_DURATION);
+ }
+
+ /**
+ * @param groupLingerDuration How long, in ms, that notifications that are members of a group
+ * are delayed within the GroupCoalescer before being posted
+ */
+ GroupCoalescer(
+ @Main DelayableExecutor mainExecutor,
+ SystemClock clock,
+ NotifLog log,
+ long groupLingerDuration) {
+ mMainExecutor = mainExecutor;
+ mClock = clock;
+ mLog = log;
+ mGroupLingerDuration = groupLingerDuration;
+ }
+
+ /**
+ * Attaches the coalescer to the pipeline, making it ready to receive events. Should only be
+ * called once.
+ */
+ public void attach(NotificationListener listenerService) {
+ listenerService.addNotificationHandler(mListener);
+ }
+
+ public void setNotificationHandler(BatchableNotificationHandler handler) {
+ mHandler = handler;
+ }
+
+ private final NotificationHandler mListener = new NotificationHandler() {
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+ maybeEmitBatch(sbn.getKey());
+ applyRanking(rankingMap);
+
+ final boolean shouldCoalesce = handleNotificationPosted(sbn, rankingMap);
+
+ if (shouldCoalesce) {
+ mLog.log(COALESCED_EVENT, String.format("Coalesced notification %s", sbn.getKey()));
+ mHandler.onNotificationRankingUpdate(rankingMap);
+ } else {
+ mHandler.onNotificationPosted(sbn, rankingMap);
+ }
+ }
+
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+ maybeEmitBatch(sbn.getKey());
+ applyRanking(rankingMap);
+ mHandler.onNotificationRemoved(sbn, rankingMap);
+ }
+
+ @Override
+ public void onNotificationRemoved(
+ StatusBarNotification sbn,
+ RankingMap rankingMap,
+ int reason) {
+ maybeEmitBatch(sbn.getKey());
+ applyRanking(rankingMap);
+ mHandler.onNotificationRemoved(sbn, rankingMap, reason);
+ }
+
+ @Override
+ public void onNotificationRankingUpdate(RankingMap rankingMap) {
+ applyRanking(rankingMap);
+ mHandler.onNotificationRankingUpdate(rankingMap);
+ }
+ };
+
+ private void maybeEmitBatch(String memberKey) {
+ CoalescedEvent event = mCoalescedEvents.get(memberKey);
+ if (event != null) {
+ mLog.log(EARLY_BATCH_EMIT,
+ String.format("Modification of %s triggered early emit of batched group %s",
+ memberKey, requireNonNull(event.getBatch()).mGroupKey));
+ emitBatch(requireNonNull(event.getBatch()));
+ }
+ }
+
+ /**
+ * @return True if the notification was coalesced and false otherwise.
+ */
+ private boolean handleNotificationPosted(
+ StatusBarNotification sbn,
+ RankingMap rankingMap) {
+
+ if (mCoalescedEvents.containsKey(sbn.getKey())) {
+ throw new IllegalStateException(
+ "Notification has already been coalesced: " + sbn.getKey());
+ }
+
+ if (sbn.isGroup()) {
+ EventBatch batch = startBatchingGroup(sbn.getGroupKey());
+ CoalescedEvent event =
+ new CoalescedEvent(
+ sbn.getKey(),
+ batch.mMembers.size(),
+ sbn,
+ requireRanking(rankingMap, sbn.getKey()),
+ batch);
+
+ batch.mMembers.add(event);
+
+ mCoalescedEvents.put(event.getKey(), event);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private EventBatch startBatchingGroup(final String groupKey) {
+ EventBatch batch = mBatches.get(groupKey);
+ if (batch == null) {
+ final EventBatch newBatch = new EventBatch(mClock.uptimeMillis(), groupKey);
+ mBatches.put(groupKey, newBatch);
+ mMainExecutor.executeDelayed(() -> emitBatch(newBatch), mGroupLingerDuration);
+
+ batch = newBatch;
+ }
+ return batch;
+ }
+
+ private void emitBatch(EventBatch batch) {
+ if (batch != mBatches.get(batch.mGroupKey)) {
+ // If we emit a batch early, we don't want to emit it a second time when its timeout
+ // expires.
+ return;
+ }
+ if (batch.mMembers.isEmpty()) {
+ throw new IllegalStateException("Batch " + batch.mGroupKey + " cannot be empty");
+ }
+
+ mBatches.remove(batch.mGroupKey);
+
+ final List<CoalescedEvent> events = new ArrayList<>(batch.mMembers);
+ for (CoalescedEvent event : events) {
+ mCoalescedEvents.remove(event.getKey());
+ event.setBatch(null);
+ }
+ events.sort(mEventComparator);
+
+ mLog.log(EMIT_EVENT_BATCH, "Emitting event batch for group " + batch.mGroupKey);
+
+ mHandler.onNotificationBatchPosted(events);
+ }
+
+ private Ranking requireRanking(RankingMap rankingMap, String key) {
+ Ranking ranking = new Ranking();
+ if (!rankingMap.getRanking(key, ranking)) {
+ throw new IllegalArgumentException("Ranking map does not contain key " + key);
+ }
+ return ranking;
+ }
+
+ private void applyRanking(RankingMap rankingMap) {
+ for (CoalescedEvent event : mCoalescedEvents.values()) {
+ Ranking ranking = new Ranking();
+ if (!rankingMap.getRanking(event.getKey(), ranking)) {
+ throw new IllegalStateException(
+ "Ranking map doesn't contain key: " + event.getKey());
+ }
+ event.setRanking(ranking);
+ }
+ }
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ long now = mClock.uptimeMillis();
+
+ int eventCount = 0;
+
+ pw.println();
+ pw.println("Coalesced notifications:");
+ for (EventBatch batch : mBatches.values()) {
+ pw.println(" Batch " + batch.mGroupKey + ":");
+ pw.println(" Created" + (now - batch.mCreatedTimestamp) + "ms ago");
+ for (CoalescedEvent event : batch.mMembers) {
+ pw.println(" " + event.getKey());
+ eventCount++;
+ }
+ }
+
+ if (eventCount != mCoalescedEvents.size()) {
+ pw.println(" ERROR: batches contain " + mCoalescedEvents.size() + " events but"
+ + " am tracking " + mCoalescedEvents.size() + " total events");
+ pw.println(" All tracked events:");
+ for (CoalescedEvent event : mCoalescedEvents.values()) {
+ pw.println(" " + event.getKey());
+ }
+ }
+ }
+
+ private final Comparator<CoalescedEvent> mEventComparator = (o1, o2) -> {
+ int cmp = Boolean.compare(
+ o2.getSbn().getNotification().isGroupSummary(),
+ o1.getSbn().getNotification().isGroupSummary());
+ if (cmp == 0) {
+ cmp = o1.getPosition() - o2.getPosition();
+ }
+ return cmp;
+ };
+
+ /**
+ * Extension of {@link NotificationListener.NotificationHandler} to include notification
+ * groups.
+ */
+ public interface BatchableNotificationHandler extends NotificationHandler {
+ /**
+ * Fired whenever the coalescer needs to emit a batch of multiple post events. This is
+ * usually the addition of a new group, but can contain just a single event, or just an
+ * update to a subset of an existing group.
+ */
+ void onNotificationBatchPosted(List<CoalescedEvent> events);
+ }
+
+ private static final int GROUP_LINGER_DURATION = 40;
+}
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 c18af80..e4a57d7 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
@@ -23,6 +23,7 @@
import com.android.systemui.log.RichEvent;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -58,7 +59,10 @@
*/
@Override
public String[] getEventLabels() {
- assert (TOTAL_EVENT_LABELS == (TOTAL_NEM_EVENT_TYPES + TOTAL_LIST_BUILDER_EVENT_TYPES));
+ assert (TOTAL_EVENT_LABELS
+ == (TOTAL_NEM_EVENT_TYPES
+ + TOTAL_LIST_BUILDER_EVENT_TYPES
+ + TOTAL_COALESCER_EVENT_TYPES));
return EVENT_LABELS;
}
@@ -141,7 +145,10 @@
"LifetimeExtended",
"RemoveIntercepted",
"InflationAborted",
- "Inflated"
+ "Inflated",
+
+ "CoalescedEvent",
+ "EarlyBatchEmit"
};
private static final int TOTAL_EVENT_LABELS = EVENT_LABELS.length;
@@ -167,7 +174,7 @@
/**
* Events related to {@link NotificationEntryManager}
*/
- public static final int NOTIF_ADDED = TOTAL_LIST_BUILDER_EVENT_TYPES + 0;
+ public static final int NOTIF_ADDED = TOTAL_LIST_BUILDER_EVENT_TYPES;
public static final int NOTIF_REMOVED = TOTAL_LIST_BUILDER_EVENT_TYPES + 1;
public static final int NOTIF_UPDATED = TOTAL_LIST_BUILDER_EVENT_TYPES + 2;
public static final int FILTER = TOTAL_LIST_BUILDER_EVENT_TYPES + 3;
@@ -180,4 +187,12 @@
public static final int INFLATION_ABORTED = TOTAL_LIST_BUILDER_EVENT_TYPES + 9;
public static final int INFLATED = TOTAL_LIST_BUILDER_EVENT_TYPES + 10;
private static final int TOTAL_NEM_EVENT_TYPES = 11;
+
+ /**
+ * Events related to {@link GroupCoalescer}
+ */
+ public static final int COALESCED_EVENT = TOTAL_NEM_EVENT_TYPES;
+ public static final int EARLY_BATCH_EMIT = TOTAL_NEM_EVENT_TYPES + 1;
+ public static final int EMIT_EVENT_BATCH = TOTAL_NEM_EVENT_TYPES + 2;
+ private static final int TOTAL_COALESCER_EVENT_TYPES = 2;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index b444fa5..add982d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification.stack;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.RectF;
@@ -32,6 +30,8 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import java.util.Objects;
+
/**
* Similar in size and appearance to the NotificationShelf, appears at the beginning of some
* notification sections. Currently only used for gentle notifications.
@@ -51,13 +51,13 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mContents = checkNotNull(findViewById(R.id.content));
+ mContents = Objects.requireNonNull(findViewById(R.id.content));
bindContents();
}
private void bindContents() {
- mLabelView = checkNotNull(findViewById(R.id.header_label));
- mClearAllButton = checkNotNull(findViewById(R.id.btn_clear_all));
+ mLabelView = Objects.requireNonNull(findViewById(R.id.header_label));
+ mClearAllButton = Objects.requireNonNull(findViewById(R.id.btn_clear_all));
if (mOnClearClickListener != null) {
mClearAllButton.setOnClickListener(mOnClearClickListener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 199d52f..c74286d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1299,7 +1299,7 @@
if (!needsAntiFalsing()) {
return false;
}
- if (mFalsingManager.isClassiferEnabled()) {
+ if (mFalsingManager.isClassifierEnabled()) {
return mFalsingManager.isFalseTouch();
}
return !mQsTouchAboveFalsingThreshold;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 78a5eb2..cd56d06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -710,7 +710,7 @@
if (!mStatusBar.isFalsingThresholdNeeded()) {
return false;
}
- if (mFalsingManager.isClassiferEnabled()) {
+ if (mFalsingManager.isClassifierEnabled()) {
return mFalsingManager.isFalseTouch();
}
if (!mTouchAboveFalsingThreshold) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 738d076..cf9d8e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -38,6 +38,11 @@
void setPowerSaveMode(boolean powerSave);
/**
+ * Returns {@code true} if the device is currently plugged in.
+ */
+ boolean isPluggedIn();
+
+ /**
* Returns {@code true} if the device is currently in power save mode.
*/
boolean isPowerSave();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index f132058..d3e6f53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -193,6 +193,11 @@
}
@Override
+ public boolean isPluggedIn() {
+ return mPluggedIn;
+ }
+
+ @Override
public boolean isPowerSave() {
return mPowerSave;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index b198678..88edf8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -23,11 +23,11 @@
import android.view.View;
import android.widget.FrameLayout;
-import com.android.internal.util.Preconditions;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -117,7 +117,7 @@
@Override
public void addCallback(BrightnessMirrorListener listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
mBrightnessMirrorListeners.add(listener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 1cb2bd4..0ab08a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -27,7 +27,6 @@
import androidx.annotation.VisibleForTesting;
-import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -36,6 +35,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -98,7 +98,7 @@
@Override
public void addCallback(@NonNull Callback callback) {
- Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
+ Objects.requireNonNull(callback, "Callback must not be null. b/128895449");
if (!mCallbacks.contains(callback)) {
mCallbacks.add(callback);
}
@@ -106,7 +106,7 @@
@Override
public void removeCallback(@NonNull Callback callback) {
- Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449");
+ Objects.requireNonNull(callback, "Callback must not be null. b/128895449");
mCallbacks.remove(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index a797287..37da236 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -16,7 +16,7 @@
package com.android.systemui.util.wakelock;
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
public class SettableWakeLock {
@@ -26,7 +26,7 @@
private boolean mAcquired;
public SettableWakeLock(WakeLock inner, String why) {
- Preconditions.checkNotNull(inner, "inner wakelock required");
+ Objects.requireNonNull(inner, "inner wakelock required");
mInner = inner;
mWhy = why;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index a19d1df..25efd32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -21,16 +21,17 @@
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
-import android.os.Handler;
import android.provider.DeviceConfig;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
+import android.util.DisplayMetrics;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
+import com.android.systemui.dock.DockManager;
+import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
@@ -47,24 +48,22 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class FalsingManagerProxyTest extends SysuiTestCase {
@Mock(stubOnly = true)
PluginManager mPluginManager;
@Mock(stubOnly = true)
ProximitySensor mProximitySensor;
- private Handler mHandler;
private FalsingManagerProxy mProxy;
private DeviceConfigProxy mDeviceConfig;
- private TestableLooper mTestableLooper;
+ private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
+ private DockManager mDockManager = new DockManagerFake();
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
- mTestableLooper = TestableLooper.get(this);
- mHandler = new Handler(mTestableLooper.getLooper());
mDeviceConfig = new DeviceConfigProxyFake();
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
@@ -79,8 +78,8 @@
@Test
public void test_brightLineFalsingManagerDisabled() {
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig, mUiBgExecutor);
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics,
+ mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
@@ -88,27 +87,27 @@
public void test_brightLineFalsingManagerEnabled() throws InterruptedException {
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
- mTestableLooper.processAllMessages();
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig, mUiBgExecutor);
+ mExecutor.runAllReady();
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics,
+ mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
}
@Test
public void test_brightLineFalsingManagerToggled() throws InterruptedException {
- mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig, mUiBgExecutor);
+ mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics,
+ mProximitySensor, mDeviceConfig, mDockManager, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
- mTestableLooper.processAllMessages();
+ mExecutor.runAllReady();
assertThat(mProxy.getInternalFalsingManager(),
instanceOf(BrightLineFalsingManager.class));
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
- mTestableLooper.processAllMessages();
+ mExecutor.runAllReady();
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
index afe4200..e88ff2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DiagonalClassifierTest.java
@@ -24,7 +24,6 @@
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
@@ -39,7 +38,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class DiagonalClassifierTest extends ClassifierTest {
// Next variable is not actually five, but is very close. 5 degrees is currently the value
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
index f0f5fc7..44454d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertThat;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
@@ -33,7 +32,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class DistanceClassifierTest extends ClassifierTest {
private FalsingDataProvider mDataProvider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
index 748c137..448c2f7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/FalsingDataProviderTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertThat;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
@@ -36,7 +35,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class FalsingDataProviderTest extends ClassifierTest {
private FalsingDataProvider mDataProvider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
index 96b2028..4f8e7c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/PointerCountClassifierTest.java
@@ -22,7 +22,6 @@
import static org.junit.Assert.assertThat;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
@@ -34,7 +33,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class PointerCountClassifierTest extends ClassifierTest {
private FalsingClassifier mClassifier;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
index 35d59c1..5b32a394 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ProximityClassifierTest.java
@@ -24,7 +24,6 @@
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import android.view.MotionEvent;
import androidx.test.filters.SmallTest;
@@ -41,7 +40,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class ProximityClassifierTest extends ClassifierTest {
private static final long NS_PER_MS = 1000000;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
index 0355dc3..4346e7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/TypeClassifierTest.java
@@ -30,7 +30,6 @@
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
@@ -42,7 +41,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class TypeClassifierTest extends ClassifierTest {
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
index 387c0da..a8cce00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/ZigZagClassifierTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertThat;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
@@ -35,7 +34,6 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
public class ZigZagClassifierTest extends ClassifierTest {
private FalsingClassifier mClassifier;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index d580234..afbe668 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -36,7 +36,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import org.junit.Before;
import org.junit.Test;
@@ -51,7 +51,7 @@
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = 0;
- @Mock private NotifServiceListener mServiceListener;
+ @Mock private NotificationHandler mNotificationHandler;
@Mock private NotificationManager mNotificationManager;
private NotificationListener mListener;
@@ -69,21 +69,21 @@
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
- mListener.addNotificationListener(mServiceListener);
+ mListener.addNotificationHandler(mNotificationHandler);
}
@Test
public void testNotificationAddCallsAddNotification() {
mListener.onNotificationPosted(mSbn, mRanking);
TestableLooper.get(this).processAllMessages();
- verify(mServiceListener).onNotificationPosted(mSbn, mRanking);
+ verify(mNotificationHandler).onNotificationPosted(mSbn, mRanking);
}
@Test
public void testNotificationRemovalCallsRemoveNotification() {
mListener.onNotificationRemoved(mSbn, mRanking);
TestableLooper.get(this).processAllMessages();
- verify(mServiceListener).onNotificationRemoved(eq(mSbn), eq(mRanking), anyInt());
+ verify(mNotificationHandler).onNotificationRemoved(eq(mSbn), eq(mRanking), anyInt());
}
@Test
@@ -91,7 +91,7 @@
mListener.onNotificationRankingUpdate(mRanking);
TestableLooper.get(this).processAllMessages();
// RankingMap may be modified by plugins.
- verify(mServiceListener).onNotificationRankingUpdate(any());
+ verify(mNotificationHandler).onNotificationRankingUpdate(any());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java
index 94b3ac4..2605402 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SbnBuilder.java
@@ -116,6 +116,27 @@
public SbnBuilder setNotification(Notification notification) {
mNotification = notification;
+ mNotificationBuilder = null;
+ return this;
+ }
+
+ public SbnBuilder setContentTitle(Context context, String contentTitle) {
+ modifyNotification(context).setContentTitle(contentTitle);
+ return this;
+ }
+
+ public SbnBuilder setContentText(Context context, String contentText) {
+ modifyNotification(context).setContentText(contentText);
+ return this;
+ }
+
+ public SbnBuilder setGroup(Context context, String groupKey) {
+ modifyNotification(context).setGroup(groupKey);
+ return this;
+ }
+
+ public SbnBuilder setGroupSummary(Context context, boolean isGroupSummary) {
+ modifyNotification(context).setGroupSummary(isGroupSummary);
return this;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java
new file mode 100644
index 0000000..c113df0b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Simulates a NotificationManager
+ *
+ * You can post and retract notifications, each with an accompanying Ranking. The simulator will
+ * keep its RankingMap up to date and call appropriate event listeners.
+ */
+public class NoManSimulator {
+ private final List<NotificationHandler> mListeners = new ArrayList<>();
+ private final Map<String, Ranking> mRankings = new ArrayMap<>();
+
+ public NoManSimulator() {
+ }
+
+ public void addListener(NotificationHandler listener) {
+ mListeners.add(listener);
+ }
+
+ public NotifEvent postNotif(NotificationEntryBuilder builder) {
+ final NotificationEntry entry = builder.build();
+ mRankings.put(entry.getKey(), entry.getRanking());
+ final RankingMap rankingMap = buildRankingMap();
+ for (NotificationHandler listener : mListeners) {
+ listener.onNotificationPosted(entry.getSbn(), rankingMap);
+ }
+ return new NotifEvent(entry.getSbn(), entry.getRanking(), rankingMap);
+ }
+
+ public NotifEvent retractNotif(StatusBarNotification sbn, int reason) {
+ assertNotNull(mRankings.remove(sbn.getKey()));
+ final RankingMap rankingMap = buildRankingMap();
+ for (NotificationHandler listener : mListeners) {
+ listener.onNotificationRemoved(sbn, rankingMap, reason);
+ }
+ return new NotifEvent(sbn, null, rankingMap);
+ }
+
+ public void issueRankingUpdate() {
+ final RankingMap rankingMap = buildRankingMap();
+ for (NotificationHandler listener : mListeners) {
+ listener.onNotificationRankingUpdate(rankingMap);
+ }
+ }
+
+ public void setRanking(String key, Ranking ranking) {
+ mRankings.put(key, ranking);
+ }
+
+ private RankingMap buildRankingMap() {
+ return new RankingMap(mRankings.values().toArray(new Ranking[0]));
+ }
+
+ public static class NotifEvent {
+ public final String key;
+ public final StatusBarNotification sbn;
+ public final Ranking ranking;
+ public final RankingMap rankingMap;
+
+ private NotifEvent(
+ StatusBarNotification sbn,
+ Ranking ranking,
+ RankingMap rankingMap) {
+ this.key = sbn.getKey();
+ this.sbn = sbn;
+ this.ranking = ranking;
+ this.rankingMap = rankingMap;
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 0dcd253..0837a42 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -19,39 +19,41 @@
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.Nullable;
import android.os.RemoteException;
import android.service.notification.NotificationListenerService.Ranking;
-import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationStats;
-import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
+import android.util.ArraySet;
import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationListener.NotifServiceListener;
import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
import com.android.systemui.util.Assert;
import org.junit.Before;
@@ -64,6 +66,8 @@
import org.mockito.Spy;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import java.util.Map;
@SmallTest
@@ -72,18 +76,20 @@
public class NotifCollectionTest extends SysuiTestCase {
@Mock private IStatusBarService mStatusBarService;
- @Mock private NotificationListener mListenerService;
+ @Mock private GroupCoalescer mGroupCoalescer;
@Spy private RecordingCollectionListener mCollectionListener;
+ @Mock private CollectionReadyForBuildListener mBuildListener;
@Spy private RecordingLifetimeExtender mExtender1 = new RecordingLifetimeExtender("Extender1");
@Spy private RecordingLifetimeExtender mExtender2 = new RecordingLifetimeExtender("Extender2");
@Spy private RecordingLifetimeExtender mExtender3 = new RecordingLifetimeExtender("Extender3");
- @Captor private ArgumentCaptor<NotifServiceListener> mListenerCaptor;
+ @Captor private ArgumentCaptor<BatchableNotificationHandler> mListenerCaptor;
@Captor private ArgumentCaptor<NotificationEntry> mEntryCaptor;
+ @Captor private ArgumentCaptor<Collection<NotificationEntry>> mBuildListCaptor;
private NotifCollection mCollection;
- private NotifServiceListener mServiceListener;
+ private BatchableNotificationHandler mNotifHandler;
private NoManSimulator mNoMan;
@@ -93,21 +99,23 @@
Assert.sMainLooper = TestableLooper.get(this).getLooper();
mCollection = new NotifCollection(mStatusBarService);
- mCollection.attach(mListenerService);
+ mCollection.attach(mGroupCoalescer);
mCollection.addCollectionListener(mCollectionListener);
+ mCollection.setBuildListener(mBuildListener);
// Capture the listener object that the collection registers with the listener service so
// we can simulate listener service events in tests below
- verify(mListenerService).addNotificationListener(mListenerCaptor.capture());
- mServiceListener = checkNotNull(mListenerCaptor.getValue());
+ verify(mGroupCoalescer).setNotificationHandler(mListenerCaptor.capture());
+ mNotifHandler = requireNonNull(mListenerCaptor.getValue());
- mNoMan = new NoManSimulator(mServiceListener);
+ mNoMan = new NoManSimulator();
+ mNoMan.addListener(mNotifHandler);
}
@Test
public void testEventDispatchedWhenNotifPosted() {
// WHEN a notification is posted
- PostedNotif notif1 = mNoMan.postNotif(
+ NotifEvent notif1 = mNoMan.postNotif(
buildNotif(TEST_PACKAGE, 3)
.setRank(4747));
@@ -121,13 +129,68 @@
}
@Test
+ public void testEventDispatchedWhenNotifBatchPosted() {
+ // GIVEN a NotifCollection with one notif already posted
+ mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2)
+ .setGroup(mContext, "group_1")
+ .setContentTitle(mContext, "Old version"));
+
+ clearInvocations(mCollectionListener);
+ clearInvocations(mBuildListener);
+
+ // WHEN three notifications from the same group are posted (one of them an update, two of
+ // them new)
+ NotificationEntry entry1 = buildNotif(TEST_PACKAGE, 1)
+ .setGroup(mContext, "group_1")
+ .build();
+ NotificationEntry entry2 = buildNotif(TEST_PACKAGE, 2)
+ .setGroup(mContext, "group_1")
+ .setContentTitle(mContext, "New version")
+ .build();
+ NotificationEntry entry3 = buildNotif(TEST_PACKAGE, 3)
+ .setGroup(mContext, "group_1")
+ .build();
+
+ mNotifHandler.onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(entry1.getKey(), 0, entry1.getSbn(), entry1.getRanking(), null),
+ new CoalescedEvent(entry2.getKey(), 1, entry2.getSbn(), entry2.getRanking(), null),
+ new CoalescedEvent(entry3.getKey(), 2, entry3.getSbn(), entry3.getRanking(), null)
+ ));
+
+ // THEN onEntryAdded is called on the new ones
+ verify(mCollectionListener, times(2)).onEntryAdded(mEntryCaptor.capture());
+
+ List<NotificationEntry> capturedAdds = mEntryCaptor.getAllValues();
+
+ assertEquals(entry1.getSbn(), capturedAdds.get(0).getSbn());
+ assertEquals(entry1.getRanking(), capturedAdds.get(0).getRanking());
+
+ assertEquals(entry3.getSbn(), capturedAdds.get(1).getSbn());
+ assertEquals(entry3.getRanking(), capturedAdds.get(1).getRanking());
+
+ // THEN onEntryUpdated is called on the middle one
+ verify(mCollectionListener).onEntryUpdated(mEntryCaptor.capture());
+ NotificationEntry capturedUpdate = mEntryCaptor.getValue();
+ assertEquals(entry2.getSbn(), capturedUpdate.getSbn());
+ assertEquals(entry2.getRanking(), capturedUpdate.getRanking());
+
+ // THEN onBuildList is called only once
+ verify(mBuildListener).onBuildList(mBuildListCaptor.capture());
+ assertEquals(new ArraySet<>(Arrays.asList(
+ capturedAdds.get(0),
+ capturedAdds.get(1),
+ capturedUpdate
+ )), new ArraySet<>(mBuildListCaptor.getValue()));
+ }
+
+ @Test
public void testEventDispatchedWhenNotifUpdated() {
// GIVEN a collection with one notif
mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
.setRank(4747));
// WHEN the notif is reposted
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
.setRank(89));
// THEN the listener is notified
@@ -145,7 +208,7 @@
mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
clearInvocations(mCollectionListener);
- PostedNotif notif = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
NotificationEntry entry = mCollectionListener.getEntry(notif.key);
clearInvocations(mCollectionListener);
@@ -161,7 +224,7 @@
@Test
public void testRankingsAreUpdatedForOtherNotifs() {
// GIVEN a collection with one notif
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
.setRank(47));
NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
@@ -178,11 +241,11 @@
@Test
public void testRankingUpdateIsProperlyIssuedToEveryone() {
// GIVEN a collection with a couple notifs
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
.setRank(3));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 8)
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 8)
.setRank(2));
- PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 77)
+ NotifEvent notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 77)
.setRank(1));
NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
@@ -217,7 +280,7 @@
@Test
public void testNotifEntriesAreNotPersistedAcrossRemovalAndReposting() {
// GIVEN a notification that has been posted
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3));
NotificationEntry entry1 = mCollectionListener.getEntry(notif1.key);
// WHEN the notification is retracted and then reposted
@@ -234,8 +297,8 @@
// GIVEN a collection with a couple notifications and a lifetime extender
mCollection.addNotificationLifetimeExtender(mExtender1);
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88, "barTag"));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88, "barTag"));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// WHEN a notification is manually dismissed
@@ -267,9 +330,9 @@
@Test(expected = IllegalStateException.class)
public void testDismissingNonExistentNotificationThrows() {
// GIVEN a collection that originally had three notifs, but where one was dismissed
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
- PostedNotif notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 99));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 99));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
@@ -292,8 +355,8 @@
mCollection.addNotificationLifetimeExtender(mExtender2);
mCollection.addNotificationLifetimeExtender(mExtender3);
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// WHEN a notification is removed
@@ -320,8 +383,8 @@
mCollection.addNotificationLifetimeExtender(mExtender2);
mCollection.addNotificationLifetimeExtender(mExtender3);
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by one of them
@@ -357,8 +420,8 @@
mCollection.addNotificationLifetimeExtender(mExtender2);
mCollection.addNotificationLifetimeExtender(mExtender3);
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by a couple of them
@@ -392,8 +455,8 @@
mCollection.addNotificationLifetimeExtender(mExtender2);
mCollection.addNotificationLifetimeExtender(mExtender3);
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by a couple of them
@@ -422,8 +485,8 @@
mExtender1.shouldExtendLifetime = true;
mExtender2.shouldExtendLifetime = true;
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by a couple of them
@@ -452,8 +515,8 @@
mExtender1.shouldExtendLifetime = true;
mExtender2.shouldExtendLifetime = true;
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by a couple of them
@@ -481,8 +544,8 @@
mExtender1.shouldExtendLifetime = true;
mExtender2.shouldExtendLifetime = true;
- PostedNotif notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
- PostedNotif notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
+ NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
+ NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
// GIVEN a notification gets lifetime-extended by a couple of them
@@ -491,7 +554,7 @@
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the notification is reposted
- PostedNotif notif2a = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88)
+ NotifEvent notif2a = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88)
.setRank(4747)
.setExplanation("Some new explanation"));
@@ -512,53 +575,6 @@
.setId(id);
}
- private static class NoManSimulator {
- private final NotifServiceListener mListener;
- private final Map<String, Ranking> mRankings = new ArrayMap<>();
-
- private NoManSimulator(
- NotifServiceListener listener) {
- mListener = listener;
- }
-
- PostedNotif postNotif(NotificationEntryBuilder builder) {
- NotificationEntry entry = builder.build();
- mRankings.put(entry.getKey(), entry.getRanking());
- mListener.onNotificationPosted(entry.getSbn(), buildRankingMap());
- return new PostedNotif(entry.getSbn(), entry.getRanking());
- }
-
- void retractNotif(StatusBarNotification sbn, int reason) {
- assertNotNull(mRankings.remove(sbn.getKey()));
- mListener.onNotificationRemoved(sbn, buildRankingMap(), reason);
- }
-
- void issueRankingUpdate() {
- mListener.onNotificationRankingUpdate(buildRankingMap());
- }
-
- void setRanking(String key, Ranking ranking) {
- mRankings.put(key, ranking);
- }
-
- private RankingMap buildRankingMap() {
- return new RankingMap(mRankings.values().toArray(new Ranking[0]));
- }
- }
-
- private static class PostedNotif {
- public final String key;
- public final StatusBarNotification sbn;
- public final Ranking ranking;
-
- private PostedNotif(StatusBarNotification sbn,
- Ranking ranking) {
- this.key = sbn.getKey();
- this.sbn = sbn;
- this.ranking = ranking;
- }
- }
-
private static class RecordingCollectionListener implements NotifCollectionListener {
private final Map<String, NotificationEntry> mLastSeenEntries = new ArrayMap<>();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
index 6e9c2c8..3e4068b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.collection;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpList;
import static org.junit.Assert.assertEquals;
@@ -67,6 +66,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
@SmallTest
@@ -105,7 +105,7 @@
mListBuilder.attach(mNotifCollection);
Mockito.verify(mNotifCollection).setBuildListener(mBuildListenerCaptor.capture());
- mReadyForBuildListener = checkNotNull(mBuildListenerCaptor.getValue());
+ mReadyForBuildListener = Objects.requireNonNull(mBuildListenerCaptor.getValue());
}
@Test
@@ -1021,7 +1021,6 @@
mPendingSet.clear();
}
- mReadyForBuildListener.onBeginDispatchToListeners();
mReadyForBuildListener.onBuildList(mEntrySet);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index e6a61d6..300ec18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -140,6 +140,28 @@
return this;
}
+ /* Delegated to Notification.Builder (via SbnBuilder) */
+
+ public NotificationEntryBuilder setContentTitle(Context context, String contentTitle) {
+ mSbnBuilder.setContentTitle(context, contentTitle);
+ return this;
+ }
+
+ public NotificationEntryBuilder setContentText(Context context, String contentText) {
+ mSbnBuilder.setContentText(context, contentText);
+ return this;
+ }
+
+ public NotificationEntryBuilder setGroup(Context context, String groupKey) {
+ mSbnBuilder.setGroup(context, groupKey);
+ return this;
+ }
+
+ public NotificationEntryBuilder setGroupSummary(Context context, boolean isGroupSummary) {
+ mSbnBuilder.setGroupSummary(context, isGroupSummary);
+ return this;
+ }
+
/* Delegated to RankingBuilder */
public NotificationEntryBuilder setRank(int rank) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java
new file mode 100644
index 0000000..7ff3240
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.NoManSimulator;
+import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class GroupCoalescerTest extends SysuiTestCase {
+
+ private GroupCoalescer mCoalescer;
+
+ @Mock private NotificationListener mListenerService;
+ @Mock private GroupCoalescer.BatchableNotificationHandler mListener;
+ @Mock private NotifLog mLog;
+
+ @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor;
+
+ private final NoManSimulator mNoMan = new NoManSimulator();
+ private final FakeSystemClock mClock = new FakeSystemClock();
+ private final FakeExecutor mExecutor = new FakeExecutor(mClock);
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mCoalescer =
+ new GroupCoalescer(
+ mExecutor,
+ mClock,
+ mLog,
+ LINGER_DURATION);
+ mCoalescer.setNotificationHandler(mListener);
+ mCoalescer.attach(mListenerService);
+
+ verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
+ NotificationHandler serviceListener = checkNotNull(mListenerCaptor.getValue());
+ mNoMan.addListener(serviceListener);
+ }
+
+ @Test
+ public void testUngroupedNotificationsAreNotCoalesced() {
+ // WHEN a notification that doesn't have a group key is posted
+ NotifEvent notif1 = mNoMan.postNotif(
+ new NotificationEntryBuilder()
+ .setId(0)
+ .setPkg(TEST_PACKAGE_A));
+ mClock.advanceTime(LINGER_DURATION);
+
+ // THEN the event is passed through to the handler
+ verify(mListener).onNotificationPosted(notif1.sbn, notif1.rankingMap);
+
+ // Then the event isn't emitted in a batch
+ verify(mListener, never()).onNotificationBatchPosted(anyList());
+ }
+
+ @Test
+ public void testGroupedNotificationsAreCoalesced() {
+ // WHEN a notification that has a group key is posted
+ NotifEvent notif1 = mNoMan.postNotif(
+ new NotificationEntryBuilder()
+ .setId(0)
+ .setPkg(TEST_PACKAGE_A)
+ .setGroup(mContext, GROUP_1));
+
+ // THEN the event is not passed on to the handler
+ verify(mListener, never()).onNotificationPosted(
+ any(StatusBarNotification.class),
+ any(RankingMap.class));
+
+ // Then the event isn't (yet) emitted in a batch
+ verify(mListener, never()).onNotificationBatchPosted(anyList());
+ }
+
+ @Test
+ public void testCoalescedNotificationsStillPassThroughRankingUpdate() {
+ // WHEN a notification that has a group key is posted
+ NotifEvent notif1 = mNoMan.postNotif(
+ new NotificationEntryBuilder()
+ .setId(0)
+ .setPkg(TEST_PACKAGE_A)
+ .setGroup(mContext, GROUP_1));
+
+ // THEN the listener receives a ranking update instead of an add
+ verify(mListener).onNotificationRankingUpdate(notif1.rankingMap);
+ }
+
+ @Test
+ public void testCoalescedNotificationsArePosted() {
+ // GIVEN three notifs are posted that are part of the same group
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setGroup(mContext, GROUP_1));
+
+ NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setGroup(mContext, GROUP_1)
+ .setGroupSummary(mContext, true));
+
+ NotifEvent notif3 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(3)
+ .setGroup(mContext, GROUP_1));
+
+ verify(mListener, never()).onNotificationPosted(
+ any(StatusBarNotification.class),
+ any(RankingMap.class));
+ verify(mListener, never()).onNotificationBatchPosted(anyList());
+
+ // WHEN enough time passes
+ mClock.advanceTime(LINGER_DURATION);
+
+ // THEN the coalesced notifs are applied. The summary is sorted to the front.
+ verify(mListener).onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(notif2.key, 1, notif2.sbn, notif2.ranking, null),
+ new CoalescedEvent(notif1.key, 0, notif1.sbn, notif1.ranking, null),
+ new CoalescedEvent(notif3.key, 2, notif3.sbn, notif3.ranking, null)
+ ));
+ }
+
+ @Test
+ public void testCoalescedEventsThatAreLaterUngroupedAreEmittedImmediatelyAndNotLater() {
+ // GIVEN a few newly posted notifications in the same group
+ NotifEvent notif1a = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setContentTitle(mContext, "Grouped message")
+ .setGroup(mContext, GROUP_1));
+ NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setGroup(mContext, GROUP_1));
+ NotifEvent notif3 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(3)
+ .setGroup(mContext, GROUP_1));
+
+ verify(mListener, never()).onNotificationPosted(
+ any(StatusBarNotification.class),
+ any(RankingMap.class));
+ verify(mListener, never()).onNotificationBatchPosted(anyList());
+
+ // WHEN one of them is updated to no longer be in the group
+ NotifEvent notif1b = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setContentTitle(mContext, "Oops no longer grouped"));
+
+ // THEN the pre-existing batch is first emitted
+ InOrder inOrder = inOrder(mListener);
+ inOrder.verify(mListener).onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(notif1a.key, 0, notif1a.sbn, notif1a.ranking, null),
+ new CoalescedEvent(notif2.key, 1, notif2.sbn, notif2.ranking, null),
+ new CoalescedEvent(notif3.key, 2, notif3.sbn, notif3.ranking, null)
+ ));
+
+ // THEN the updated notif is emitted
+ inOrder.verify(mListener).onNotificationPosted(notif1b.sbn, notif1b.rankingMap);
+
+ // WHEN the time runs out on the remainder of the group
+ clearInvocations(mListener);
+ mClock.advanceTime(LINGER_DURATION);
+
+ // THEN no lingering batch is applied
+ verify(mListener, never()).onNotificationBatchPosted(anyList());
+ }
+
+ @Test
+ public void testUpdatingCoalescedNotifTriggersBatchEmit() {
+ // GIVEN two grouped, coalesced notifications
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setGroup(mContext, GROUP_1));
+ NotifEvent notif2a = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setContentTitle(mContext, "Version 1")
+ .setGroup(mContext, GROUP_1));
+
+ // WHEN one of them gets updated
+ NotifEvent notif2b = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setContentTitle(mContext, "Version 2")
+ .setGroup(mContext, GROUP_1));
+
+ // THEN first, the coalesced group is emitted
+ verify(mListener).onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(notif1.key, 0, notif1.sbn, notif1.ranking, null),
+ new CoalescedEvent(notif2a.key, 1, notif2a.sbn, notif2a.ranking, null)
+ ));
+ verify(mListener, never()).onNotificationPosted(
+ any(StatusBarNotification.class),
+ any(RankingMap.class));
+
+ // THEN second, the update is emitted
+ mClock.advanceTime(LINGER_DURATION);
+ verify(mListener).onNotificationBatchPosted(Collections.singletonList(
+ new CoalescedEvent(notif2b.key, 0, notif2b.sbn, notif2b.ranking, null)
+ ));
+ }
+
+ @Test
+ public void testRemovingCoalescedNotifTriggersBatchEmit() {
+ // GIVEN two grouped, coalesced notifications
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setGroup(mContext, GROUP_1));
+ NotifEvent notif2a = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setGroup(mContext, GROUP_1));
+
+ // WHEN one of them gets retracted
+ NotifEvent notif2b = mNoMan.retractNotif(notif2a.sbn, 0);
+
+ // THEN first, the coalesced group is emitted
+ InOrder inOrder = inOrder(mListener);
+ inOrder.verify(mListener).onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(notif1.key, 0, notif1.sbn, notif1.ranking, null),
+ new CoalescedEvent(notif2a.key, 1, notif2a.sbn, notif2a.ranking, null)
+ ));
+
+ // THEN second, the removal is emitted
+ inOrder.verify(mListener).onNotificationRemoved(notif2b.sbn, notif2b.rankingMap, 0);
+ }
+
+ @Test
+ public void testRankingsAreUpdated() {
+ // GIVEN a couple coalesced notifications
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1)
+ .setGroup(mContext, GROUP_1));
+ NotifEvent notif2 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_A)
+ .setId(2)
+ .setGroup(mContext, GROUP_1));
+
+ // WHEN an update to an unrelated notification comes in that updates their rankings
+ Ranking ranking1b = new RankingBuilder()
+ .setKey(notif1.key)
+ .setLastAudiblyAlertedMs(4747)
+ .build();
+ Ranking ranking2b = new RankingBuilder()
+ .setKey(notif2.key)
+ .setLastAudiblyAlertedMs(3333)
+ .build();
+ mNoMan.setRanking(notif1.key, ranking1b);
+ mNoMan.setRanking(notif2.key, ranking2b);
+ mNoMan.postNotif(new NotificationEntryBuilder()
+ .setPkg(TEST_PACKAGE_B)
+ .setId(17));
+
+ // THEN they have the new rankings when they are eventually emitted
+ mClock.advanceTime(LINGER_DURATION);
+ verify(mListener).onNotificationBatchPosted(Arrays.asList(
+ new CoalescedEvent(notif1.key, 0, notif1.sbn, ranking1b, null),
+ new CoalescedEvent(notif2.key, 1, notif2.sbn, ranking2b, null)
+ ));
+ }
+
+ private static final long LINGER_DURATION = 4700;
+
+ private static final String TEST_PACKAGE_A = "com.test.package_a";
+ private static final String TEST_PACKAGE_B = "com.test.package_b";
+ private static final String GROUP_1 = "group_1";
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
index a024454..3d59d61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
@@ -18,8 +18,6 @@
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -50,6 +48,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Objects;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -85,11 +85,11 @@
// Capture the entry listener object so we can simulate events in tests below
verify(mEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
- mEntryListener = checkNotNull(mListenerCaptor.getValue());
+ mEntryListener = Objects.requireNonNull(mListenerCaptor.getValue());
// Capture the callback object so we can simulate callback events in tests below
verify(mCommandQueue).addCallback(mCallbacksCaptor.capture());
- mCallbacks = checkNotNull(mCallbacksCaptor.getValue());
+ mCallbacks = Objects.requireNonNull(mCallbacksCaptor.getValue());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
index e15ca1d..27b225e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeSensorManager.java
@@ -30,14 +30,13 @@
import android.os.SystemClock;
import android.util.ArraySet;
-import com.android.internal.util.Preconditions;
-
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -113,7 +112,7 @@
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
for (FakeGenericSensor s : mSensors) {
if (sensor == null || s.mSensor == sensor) {
s.mListeners.remove(listener);
@@ -125,8 +124,8 @@
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs,
Handler handler, int maxReportLatencyUs, int reservedFlags) {
- Preconditions.checkNotNull(sensor);
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(sensor);
+ Objects.requireNonNull(listener);
for (FakeGenericSensor s : mSensors) {
if (s.mSensor == sensor) {
s.mListeners.add(listener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
index df76f01..8ec4cb8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeBatteryController.java
@@ -45,6 +45,11 @@
}
@Override
+ public boolean isPluggedIn() {
+ return false;
+ }
+
+ @Override
public boolean isPowerSave() {
return false;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
index 6a1f1a5..a0428a5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiTapAndHold.java
@@ -38,6 +38,12 @@
}
@Override
+ protected void onUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ super.onUp(event, rawEvent, policyFlags);
+ cancelAfterDoubleTapTimeout(event, rawEvent, policyFlags);
+ }
+
+ @Override
public String getGestureName() {
switch (mTargetTaps) {
case 2:
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index f6eb31b..ba890c5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -286,10 +286,6 @@
@Override
public void onDoubleTapAndHold() {
- // Pointers should not be zero when running this command.
- if (mState.getLastReceivedEvent().getPointerCount() == 0) {
- return;
- }
// Try to use the standard accessibility API to long click
if (!mAms.performActionOnAccessibilityFocusedItem(
AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK)) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index c689ed1..03d9626 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -288,7 +288,14 @@
boolean isTemporary) {
mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary);
synchronized (mLock) {
- getServiceForUserLocked(userId).updateRemoteAugmentedAutofillService();
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service == null) {
+ // If we cannot get the service from the services cache, it will call
+ // updateRemoteAugmentedAutofillService() finally. Skip call this update again.
+ getServiceForUserLocked(userId);
+ } else {
+ service.updateRemoteAugmentedAutofillService();
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 202f900..bf801fc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -970,6 +970,8 @@
} else {
pw.println(compatPkgs);
}
+ pw.print(prefix); pw.print("Inline Suggestions Enabled: ");
+ pw.println(isInlineSuggestionsEnabled());
pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
pw.print(prefix); pw.print("Disabled apps: ");
@@ -1120,6 +1122,14 @@
}
@GuardedBy("mLock")
+ boolean isInlineSuggestionsEnabled() {
+ if (mInfo != null) {
+ return mInfo.isInlineSuggestionsEnabled();
+ }
+ return false;
+ }
+
+ @GuardedBy("mLock")
@Nullable RemoteAugmentedAutofillService getRemoteAugmentedAutofillServiceLocked() {
if (mRemoteAugmentedAutofillService == null) {
final String serviceName = mMaster.mAugmentedAutofillResolver.getServiceName(mUserId);
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java
new file mode 100644
index 0000000..3af15c7
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionFactory.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import static com.android.server.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.service.autofill.Dataset;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.autofill.AutofillId;
+import android.view.autofill.IAutoFillManagerClient;
+import android.view.inline.InlinePresentationSpec;
+import android.view.inputmethod.InlineSuggestion;
+import android.view.inputmethod.InlineSuggestionInfo;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import android.view.inputmethod.InlineSuggestionsResponse;
+
+import com.android.internal.view.inline.IInlineContentCallback;
+import com.android.internal.view.inline.IInlineContentProvider;
+import com.android.server.autofill.ui.InlineSuggestionUi;
+
+import java.util.ArrayList;
+
+
+/**
+ * @hide
+ */
+public final class InlineSuggestionFactory {
+ private static final String TAG = "InlineSuggestionFactory";
+
+ /**
+ * Creates an {@link InlineSuggestionsResponse} with the {@code datasets} provided by
+ * augmented autofill service.
+ */
+ public static InlineSuggestionsResponse createAugmentedInlineSuggestionsResponse(
+ int sessionId,
+ @NonNull Dataset[] datasets,
+ @NonNull AutofillId autofillId,
+ @NonNull InlineSuggestionsRequest request,
+ @NonNull Handler uiHandler,
+ @NonNull Context context,
+ @NonNull IAutoFillManagerClient client) {
+ if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
+
+ final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
+ final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(context);
+ for (Dataset dataset : datasets) {
+ // TODO(b/146453195): use the spec in the dataset.
+ InlinePresentationSpec spec = request.getPresentationSpecs().get(0);
+ if (spec == null) {
+ Slog.w(TAG, "InlinePresentationSpec is not provided in the response data set");
+ continue;
+ }
+ InlineSuggestion inlineSuggestion = createAugmentedInlineSuggestion(sessionId, dataset,
+ autofillId, spec, uiHandler, inlineSuggestionUi, client);
+ inlineSuggestions.add(inlineSuggestion);
+ }
+ return new InlineSuggestionsResponse(inlineSuggestions);
+ }
+
+ private static InlineSuggestion createAugmentedInlineSuggestion(int sessionId,
+ @NonNull Dataset dataset,
+ @NonNull AutofillId autofillId,
+ @NonNull InlinePresentationSpec spec,
+ @NonNull Handler uiHandler,
+ @NonNull InlineSuggestionUi inlineSuggestionUi,
+ @NonNull IAutoFillManagerClient client) {
+ // TODO(b/146453195): fill in the autofill hint properly.
+ final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
+ spec, InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""});
+ final View.OnClickListener onClickListener = createOnClickListener(sessionId, dataset,
+ client);
+ final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
+ createInlineContentProvider(autofillId, dataset, uiHandler, inlineSuggestionUi,
+ onClickListener));
+ return inlineSuggestion;
+ }
+
+ private static IInlineContentProvider.Stub createInlineContentProvider(
+ @NonNull AutofillId autofillId, @NonNull Dataset dataset, @NonNull Handler uiHandler,
+ @NonNull InlineSuggestionUi inlineSuggestionUi,
+ @Nullable View.OnClickListener onClickListener) {
+ return new IInlineContentProvider.Stub() {
+ @Override
+ public void provideContent(int width, int height,
+ IInlineContentCallback callback) {
+ uiHandler.post(() -> {
+ SurfaceControl sc = inlineSuggestionUi.inflate(dataset, autofillId,
+ width, height, onClickListener);
+ try {
+ callback.onContent(sc);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Encounter exception calling back with inline content.");
+ }
+ });
+ }
+ };
+ }
+
+ private static View.OnClickListener createOnClickListener(int sessionId,
+ @NonNull Dataset dataset,
+ @NonNull IAutoFillManagerClient client) {
+ return v -> {
+ if (sDebug) Slog.d(TAG, "Inline suggestion clicked");
+ try {
+ client.autofill(sessionId, dataset.getFieldIds(), dataset.getFieldValues());
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Encounter exception autofilling the values");
+ }
+ };
+ }
+
+ private InlineSuggestionFactory() {
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index c5011b3..2a7357b 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -46,12 +46,15 @@
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
+import android.view.inputmethod.InlineSuggestionsRequest;
import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.ServiceConnector;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.view.IInlineSuggestionsResponseCallback;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
@@ -137,7 +140,9 @@
*/
public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client,
int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId,
- @Nullable AutofillValue focusedValue) {
+ @Nullable AutofillValue focusedValue,
+ @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
+ @Nullable IInlineSuggestionsResponseCallback inlineSuggestionsCallback) {
long requestTime = SystemClock.elapsedRealtime();
AtomicReference<ICancellationSignal> cancellationRef = new AtomicReference<>();
@@ -151,10 +156,13 @@
final IBinder realClient = resultData
.getBinder(AutofillManager.EXTRA_AUGMENTED_AUTOFILL_CLIENT);
service.onFillRequest(sessionId, realClient, taskId, activityComponent,
- focusedId, focusedValue, requestTime, new IFillCallback.Stub() {
+ focusedId, focusedValue, requestTime, inlineSuggestionsRequest,
+ new IFillCallback.Stub() {
@Override
public void onSuccess(@Nullable Dataset[] inlineSuggestionsData) {
- // TODO(b/146453195): handle non-null inline suggestions data.
+ maybeHandleInlineSuggestions(sessionId, inlineSuggestionsData,
+ focusedId, inlineSuggestionsRequest,
+ inlineSuggestionsCallback, client);
requestAutofill.complete(null);
}
@@ -216,6 +224,26 @@
});
}
+ private void maybeHandleInlineSuggestions(int sessionId,
+ @Nullable Dataset[] inlineSuggestionsData, @NonNull AutofillId focusedId,
+ @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
+ @Nullable IInlineSuggestionsResponseCallback inlineSuggestionsCallback,
+ @NonNull IAutoFillManagerClient client) {
+ if (inlineSuggestionsRequest == null
+ || ArrayUtils.isEmpty(inlineSuggestionsData)
+ || inlineSuggestionsCallback == null) {
+ return;
+ }
+ try {
+ inlineSuggestionsCallback.onInlineSuggestionsResponse(
+ InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(
+ sessionId, inlineSuggestionsData, focusedId, inlineSuggestionsRequest,
+ getJobHandler(), mContext, client));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception sending inline suggestions response back to IME.");
+ }
+ }
+
@Override
public String toString() {
return "RemoteAugmentedAutofillService["
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 5af4399..2c8bc22 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -323,7 +323,7 @@
mInlineSuggestionsResponseCallbackFuture;
@Nullable
- private InlineSuggestionsRequestCallback mInlineSuggestionsRequestCallback;
+ private InlineSuggestionsRequestCallbackImpl mInlineSuggestionsRequestCallback;
private static final int INLINE_REQUEST_TIMEOUT_MS = 1000;
@@ -424,19 +424,7 @@
final ArrayList<FillContext> contexts =
mergePreviousSessionLocked(/* forSave= */ false);
- InlineSuggestionsRequest suggestionsRequest = null;
- if (mSuggestionsRequestFuture != null) {
- try {
- suggestionsRequest = mSuggestionsRequestFuture.get(
- INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (TimeoutException e) {
- Log.w(TAG, "Exception getting inline suggestions request in time: " + e);
- } catch (CancellationException e) {
- Log.w(TAG, "Inline suggestions request cancelled");
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
+ final InlineSuggestionsRequest suggestionsRequest = getInlineSuggestionsRequest();
request = new FillRequest(requestId, contexts, mClientState, flags,
suggestionsRequest);
@@ -624,9 +612,8 @@
/**
* Returns whether inline suggestions are enabled for Autofill.
*/
- // TODO(b/137800469): Implement this
private boolean isInlineSuggestionsEnabled() {
- return true;
+ return mService.isInlineSuggestionsEnabled();
}
/**
@@ -639,7 +626,7 @@
mInlineSuggestionsResponseCallbackFuture = new CompletableFuture<>();
if (mInlineSuggestionsRequestCallback == null) {
- mInlineSuggestionsRequestCallback = new InlineSuggestionsRequestCallback(this);
+ mInlineSuggestionsRequestCallback = new InlineSuggestionsRequestCallbackImpl(this);
}
mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(
@@ -649,11 +636,11 @@
requestNewFillResponseLocked(viewState, newState, flags);
}
- private static final class InlineSuggestionsRequestCallback
+ private static final class InlineSuggestionsRequestCallbackImpl
extends IInlineSuggestionsRequestCallback.Stub {
private final WeakReference<Session> mSession;
- private InlineSuggestionsRequestCallback(Session session) {
+ private InlineSuggestionsRequestCallbackImpl(Session session) {
mSession = new WeakReference<>(session);
}
@@ -2692,21 +2679,8 @@
*/
private boolean requestShowInlineSuggestions(List<Slice> inlineSuggestionSlices,
FillResponse response) {
- IInlineSuggestionsResponseCallback inlineContentCallback = null;
- synchronized (mLock) {
- if (mInlineSuggestionsResponseCallbackFuture != null) {
- try {
- inlineContentCallback = mInlineSuggestionsResponseCallbackFuture.get(
- INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (TimeoutException e) {
- Log.w(TAG, "Exception getting inline suggestions callback in time: " + e);
- } catch (CancellationException e) {
- Log.w(TAG, "Inline suggestions callback cancelled");
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
- }
+ final IInlineSuggestionsResponseCallback inlineContentCallback =
+ getInlineSuggestionsResponseCallback();
if (inlineContentCallback == null) {
Log.w(TAG, "Session input method callback is not set yet");
@@ -3063,9 +3037,12 @@
final AutofillId focusedId = AutofillId.withoutSession(mCurrentViewId);
- // TODO(b/137800469): implement inlined suggestions for augmented autofill
+ final InlineSuggestionsRequest inlineSuggestionsRequest = getInlineSuggestionsRequest();
+ final IInlineSuggestionsResponseCallback inlineSuggestionsResponseCallback =
+ getInlineSuggestionsResponseCallback();
+
remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, focusedId,
- currentValue);
+ currentValue, inlineSuggestionsRequest, inlineSuggestionsResponseCallback);
if (mAugmentedAutofillDestroyer == null) {
mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
@@ -3073,6 +3050,40 @@
return mAugmentedAutofillDestroyer;
}
+ @Nullable
+ private InlineSuggestionsRequest getInlineSuggestionsRequest() {
+ if (mSuggestionsRequestFuture != null) {
+ try {
+ return mSuggestionsRequestFuture.get(
+ INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ Log.w(TAG, "Exception getting inline suggestions request in time: " + e);
+ } catch (CancellationException e) {
+ Log.w(TAG, "Inline suggestions request cancelled");
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private IInlineSuggestionsResponseCallback getInlineSuggestionsResponseCallback() {
+ if (mInlineSuggestionsResponseCallbackFuture != null) {
+ try {
+ return mInlineSuggestionsResponseCallbackFuture.get(
+ INLINE_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ Log.w(TAG, "Exception getting inline suggestions callback in time: " + e);
+ } catch (CancellationException e) {
+ Log.w(TAG, "Inline suggestions callback cancelled");
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+
@GuardedBy("mLock")
private void cancelAugmentedAutofillLocked() {
final RemoteAugmentedAutofillService remoteService = mService
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index e57b7b3..0511bf2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -24,8 +24,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.metrics.LogMaker;
import android.os.Bundle;
@@ -40,13 +38,9 @@
import android.util.Slog;
import android.view.KeyEvent;
import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.WindowManager;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
import android.view.autofill.IAutofillWindowPresenter;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
@@ -189,8 +183,16 @@
Slog.w(TAG, "getSuggestionSurfaceForShowing() called with null dataset");
}
mHandler.post(() -> {
- final SurfaceControl suggestionSurface = inflateInlineSuggestion(dataset, response,
- autofillId, width, height);
+ final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(mContext);
+ final SurfaceControl suggestionSurface = inlineSuggestionUi.inflate(dataset,
+ autofillId, width, height, v -> {
+ Slog.d(TAG, "Inline suggestion clicked");
+ hideFillUiUiThread(mCallback, true);
+ if (mCallback != null) {
+ final int datasetIndex = response.getDatasets().indexOf(dataset);
+ mCallback.fill(response.getRequestId(), datasetIndex, dataset);
+ }
+ });
try {
cb.onContent(suggestionSurface);
@@ -201,51 +203,6 @@
}
/**
- * TODO(b/137800469): Fill in javadoc, generate custom templated view for inline suggestions.
- * TODO: Move to ExtServices.
- *
- * @return a {@link SurfaceControl} with the inflated content embedded in it.
- */
- private SurfaceControl inflateInlineSuggestion(@NonNull Dataset dataset,
- @NonNull FillResponse response, AutofillId autofillId, int width, int height) {
- Slog.i(TAG, "inflate() called");
- final Context context = mContext;
- final int index = dataset.getFieldIds().indexOf(autofillId);
- if (index < 0) {
- Slog.w(TAG, "inflateInlineSuggestion(): AutofillId=" + autofillId
- + " not found in dataset");
- }
-
- final AutofillValue datasetValue = dataset.getFieldValues().get(index);
- //TODO(b/137800469): Pass in inputToken from IME.
- final SurfaceControlViewHost wvr = new SurfaceControlViewHost(context, context.getDisplay(),
- (IBinder) null);
- // TODO(b/134365580): Use the package instead of the SurfaceControl itself
- // for accessibility support.
- final SurfaceControl sc = wvr.getSurfacePackage().getSurfaceControl();
-
- TextView textView = new TextView(context);
- textView.setText(datasetValue.getTextValue());
- textView.setBackgroundColor(Color.WHITE);
- textView.setTextColor(Color.BLACK);
- textView.setOnClickListener(v -> {
- Slog.d(TAG, "Inline suggestion clicked");
- hideFillUiUiThread(mCallback, true);
- if (mCallback != null) {
- final int datasetIndex = response.getDatasets().indexOf(dataset);
- mCallback.fill(response.getRequestId(), datasetIndex, dataset);
- }
- });
-
- WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(width, height,
- WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE);
- wvr.addView(textView, lp);
-
- return sc;
- }
-
- /**
* Shows the fill UI, removing the previous fill UI if the has changed.
*
* @param focusedId the currently focused field
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java
new file mode 100644
index 0000000..17cb739
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionUi.java
@@ -0,0 +1,89 @@
+/*
+ * 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.autofill.ui;
+
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.IBinder;
+import android.service.autofill.Dataset;
+import android.util.Log;
+import android.util.Slog;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.widget.TextView;
+
+/**
+ * This is a temporary inline suggestion UI inflater which will be replaced by the ExtServices
+ * implementation.
+ *
+ * TODO(b/146453086): remove this class once autofill ext service is implemented.
+ *
+ * @hide
+ */
+public class InlineSuggestionUi {
+
+ private static final String TAG = "InlineSuggestionUi";
+
+ private final Context mContext;
+
+ public InlineSuggestionUi(Context context) {
+ this.mContext = context;
+ }
+
+ /**
+ * Returns a {@link SurfaceControl} with the inflated content embedded in it.
+ */
+ @MainThread
+ @Nullable
+ public SurfaceControl inflate(@NonNull Dataset dataset, @NonNull AutofillId autofillId,
+ int width, int height, @Nullable View.OnClickListener onClickListener) {
+ Log.d(TAG, "Inflating the inline suggestion UI");
+ final int index = dataset.getFieldIds().indexOf(autofillId);
+ if (index < 0) {
+ Slog.w(TAG, "inflateInlineSuggestion(): AutofillId=" + autofillId
+ + " not found in dataset");
+ return null;
+ }
+ final AutofillValue datasetValue = dataset.getFieldValues().get(index);
+ //TODO(b/137800469): Pass in inputToken from IME.
+ final SurfaceControlViewHost wvr = new SurfaceControlViewHost(mContext,
+ mContext.getDisplay(), (IBinder) null);
+ final SurfaceControl sc = wvr.getSurfacePackage().getSurfaceControl();
+
+ TextView textView = new TextView(mContext);
+ textView.setText(datasetValue.getTextValue());
+ textView.setBackgroundColor(Color.WHITE);
+ textView.setTextColor(Color.BLACK);
+ if (onClickListener != null) {
+ textView.setOnClickListener(onClickListener);
+ }
+
+ WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(width, height,
+ WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
+ wvr.addView(textView, lp);
+ return sc;
+ }
+}
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 7d5b176..72e170f 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -63,6 +63,7 @@
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* Class to keep track of the information related to "force app standby", which includes:
@@ -416,12 +417,12 @@
}
mStarted = true;
- mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
- mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
- mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
- mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
- mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
- mAppStandbyInternal = Preconditions.checkNotNull(injectAppStandbyInternal());
+ mIActivityManager = Objects.requireNonNull(injectIActivityManager());
+ mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal());
+ mAppOpsManager = Objects.requireNonNull(injectAppOpsManager());
+ mAppOpsService = Objects.requireNonNull(injectIAppOpsService());
+ mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal());
+ mAppStandbyInternal = Objects.requireNonNull(injectAppStandbyInternal());
mFlagsObserver = new FeatureFlagsObserver();
mFlagsObserver.register();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bb78ace..deac1e3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -47,8 +47,6 @@
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.BroadcastOptions;
@@ -904,7 +902,7 @@
* @see IpConnectivityMetrics.Logger
*/
public IpConnectivityMetrics.Logger getMetricsLogger() {
- return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
+ return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
"no IpConnectivityMetrics service");
}
@@ -933,7 +931,7 @@
IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) {
if (DBG) log("ConnectivityService starting up");
- mDeps = checkNotNull(deps, "missing Dependencies");
+ mDeps = Objects.requireNonNull(deps, "missing Dependencies");
mSystemProperties = mDeps.getSystemProperties();
mNetIdManager = mDeps.makeNetIdManager();
@@ -962,14 +960,14 @@
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
- mContext = checkNotNull(context, "missing Context");
- mNMS = checkNotNull(netManager, "missing INetworkManagementService");
- mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
- mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
- mPolicyManagerInternal = checkNotNull(
+ mContext = Objects.requireNonNull(context, "missing Context");
+ mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
+ mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService");
+ mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager");
+ mPolicyManagerInternal = Objects.requireNonNull(
LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal");
- mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
+ mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
mNetd = netd;
@@ -5195,7 +5193,7 @@
@Override
public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
PendingIntent operation) {
- checkNotNull(operation, "PendingIntent cannot be null.");
+ Objects.requireNonNull(operation, "PendingIntent cannot be null.");
networkCapabilities = new NetworkCapabilities(networkCapabilities);
enforceNetworkRequestPermissions(networkCapabilities);
enforceMeteredApnPolicy(networkCapabilities);
@@ -5222,7 +5220,7 @@
@Override
public void releasePendingNetworkRequest(PendingIntent operation) {
- checkNotNull(operation, "PendingIntent cannot be null.");
+ Objects.requireNonNull(operation, "PendingIntent cannot be null.");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
getCallingUid(), 0, operation));
}
@@ -5280,7 +5278,7 @@
@Override
public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
PendingIntent operation) {
- checkNotNull(operation, "PendingIntent cannot be null.");
+ Objects.requireNonNull(operation, "PendingIntent cannot be null.");
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/services/core/java/com/android/server/ExplicitHealthCheckController.java
index f7c4aac..77059d9 100644
--- a/services/core/java/com/android/server/ExplicitHealthCheckController.java
+++ b/services/core/java/com/android/server/ExplicitHealthCheckController.java
@@ -47,6 +47,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
@@ -113,9 +114,9 @@
Slog.wtf(TAG, "Resetting health check controller callbacks");
}
- mPassedConsumer = Preconditions.checkNotNull(passedConsumer);
- mSupportedConsumer = Preconditions.checkNotNull(supportedConsumer);
- mNotifySyncRunnable = Preconditions.checkNotNull(notifySyncRunnable);
+ mPassedConsumer = Objects.requireNonNull(passedConsumer);
+ mSupportedConsumer = Objects.requireNonNull(supportedConsumer);
+ mNotifySyncRunnable = Objects.requireNonNull(notifySyncRunnable);
}
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a629b3f..c987620 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -25,8 +25,6 @@
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.Context;
@@ -76,6 +74,7 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* A service to manage multiple clients that want to access the IpSec API. The service is
@@ -566,7 +565,7 @@
}
void put(int key, RefcountedResource<T> obj) {
- checkNotNull(obj, "Null resources cannot be added");
+ Objects.requireNonNull(obj, "Null resources cannot be added");
mArray.put(key, obj);
}
@@ -1101,7 +1100,7 @@
if (requestedSpi > 0 && requestedSpi < 256) {
throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255.");
}
- checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
+ Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1218,7 +1217,7 @@
throw new IllegalArgumentException(
"Specified port number must be a valid non-reserved UDP port");
}
- checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
+ Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
int callingUid = Binder.getCallingUid();
UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1278,8 +1277,8 @@
String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
String callingPackage) {
enforceTunnelFeatureAndPermissions(callingPackage);
- checkNotNull(binder, "Null Binder passed to createTunnelInterface");
- checkNotNull(underlyingNetwork, "No underlying network was specified");
+ Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface");
+ Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
checkInetAddress(localAddr);
checkInetAddress(remoteAddr);
@@ -1556,7 +1555,7 @@
"IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
}
- checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
+ Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels");
switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
case AppOpsManager.MODE_DEFAULT:
mContext.enforceCallingOrSelfPermission(
@@ -1625,12 +1624,12 @@
@Override
public synchronized IpSecTransformResponse createTransform(
IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
- checkNotNull(c);
+ Objects.requireNonNull(c);
if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
enforceTunnelFeatureAndPermissions(callingPackage);
}
checkIpSecConfig(c);
- checkNotNull(binder, "Null Binder passed to createTransform");
+ Objects.requireNonNull(binder, "Null Binder passed to createTransform");
final int resourceId = mNextResourceId++;
UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index cad917b..c5f1923 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -23,7 +23,6 @@
import static android.location.LocationManager.PASSIVE_PROVIDER;
import static android.os.PowerManager.locationPowerSaveModeToString;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
import android.Manifest;
@@ -121,6 +120,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
@@ -821,7 +821,7 @@
@GuardedBy("mLock")
public void attachLocked(AbstractLocationProvider provider) {
- checkNotNull(provider);
+ Objects.requireNonNull(provider);
checkState(mProvider == null);
if (D) {
@@ -1430,7 +1430,7 @@
@Override
public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
String featureId, String listenerIdentifier) {
- Preconditions.checkNotNull(listenerIdentifier);
+ Objects.requireNonNull(listenerIdentifier);
return mGnssManagerService == null ? false : mGnssManagerService.addGnssBatchingCallback(
callback, packageName, featureId, listenerIdentifier);
@@ -2119,7 +2119,7 @@
public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
PendingIntent intent, String packageName, String featureId,
String listenerIdentifier) {
- Preconditions.checkNotNull(listenerIdentifier);
+ Objects.requireNonNull(listenerIdentifier);
synchronized (mLock) {
if (request == null) request = DEFAULT_LOCATION_REQUEST;
@@ -2470,7 +2470,7 @@
@Override
public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
String packageName, String featureId, String listenerIdentifier) {
- Preconditions.checkNotNull(listenerIdentifier);
+ Objects.requireNonNull(listenerIdentifier);
if (request == null) request = DEFAULT_LOCATION_REQUEST;
int allowedResolutionLevel = getCallerAllowedResolutionLevel();
@@ -2567,7 +2567,7 @@
@Override
public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
String packageName, String featureId, String listenerIdentifier) {
- Preconditions.checkNotNull(listenerIdentifier);
+ Objects.requireNonNull(listenerIdentifier);
return mGnssManagerService == null ? false
: mGnssManagerService.addGnssMeasurementsListener(listener, packageName, featureId,
@@ -2600,7 +2600,7 @@
@Override
public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
String packageName, String featureId, String listenerIdentifier) {
- Preconditions.checkNotNull(listenerIdentifier);
+ Objects.requireNonNull(listenerIdentifier);
return mGnssManagerService == null ? false
: mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index ad02aad..eac767f 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -46,6 +46,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.LinkedList;
+import java.util.Objects;
/**
* Generic connector class for interfacing with a native daemon which uses the
@@ -126,7 +127,7 @@
*/
public void setWarnIfHeld(Object warnIfHeld) {
Preconditions.checkState(mWarnIfHeld == null);
- mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+ mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
}
@Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0d496b6..1f73650 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -109,6 +109,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* @hide
@@ -456,7 +457,7 @@
@Override
public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
NetworkStack.checkNetworkStackPermission(mContext);
- Preconditions.checkNotNull(provider);
+ Objects.requireNonNull(provider);
synchronized(mTetheringStatsProviders) {
mTetheringStatsProviders.put(provider, name);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 22fa8ff4..c474f47 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2102,7 +2102,7 @@
public void setVolumeNickname(String fsUuid, String nickname) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- Preconditions.checkNotNull(fsUuid);
+ Objects.requireNonNull(fsUuid);
synchronized (mLock) {
final VolumeRecord rec = mRecords.get(fsUuid);
rec.nickname = nickname;
@@ -2115,7 +2115,7 @@
public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- Preconditions.checkNotNull(fsUuid);
+ Objects.requireNonNull(fsUuid);
synchronized (mLock) {
final VolumeRecord rec = mRecords.get(fsUuid);
rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
@@ -2128,7 +2128,7 @@
public void forgetVolume(String fsUuid) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
- Preconditions.checkNotNull(fsUuid);
+ Objects.requireNonNull(fsUuid);
synchronized (mLock) {
final VolumeRecord rec = mRecords.remove(fsUuid);
@@ -2534,7 +2534,7 @@
@Override
public String getMountedObbPath(String rawPath) {
- Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+ Objects.requireNonNull(rawPath, "rawPath cannot be null");
warnOnNotMounted();
@@ -2552,7 +2552,7 @@
@Override
public boolean isObbMounted(String rawPath) {
- Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+ Objects.requireNonNull(rawPath, "rawPath cannot be null");
synchronized (mObbMounts) {
return mObbPathToStateMap.containsKey(rawPath);
}
@@ -2561,10 +2561,10 @@
@Override
public void mountObb(String rawPath, String canonicalPath, String key,
IObbActionListener token, int nonce, ObbInfo obbInfo) {
- Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
- Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
- Preconditions.checkNotNull(token, "token cannot be null");
- Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
+ Objects.requireNonNull(rawPath, "rawPath cannot be null");
+ Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
+ Objects.requireNonNull(token, "token cannot be null");
+ Objects.requireNonNull(obbInfo, "obbIfno cannot be null");
final int callingUid = Binder.getCallingUid();
final ObbState obbState = new ObbState(rawPath, canonicalPath,
@@ -2578,7 +2578,7 @@
@Override
public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
- Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+ Objects.requireNonNull(rawPath, "rawPath cannot be null");
final ObbState existingState;
synchronized (mObbMounts) {
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index 5ed94e3..179780d 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -28,6 +28,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -73,7 +74,7 @@
*/
public static @NonNull Future<?> submit(@NonNull Runnable runnable,
@NonNull String description) {
- Preconditions.checkNotNull(description, "description cannot be null");
+ Objects.requireNonNull(description, "description cannot be null");
SystemServerInitThreadPool instance;
synchronized (LOCK) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index c741fce..783715c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -785,9 +785,11 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
r.callback.onServiceStateChanged(rawSs);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(false));
} else {
- r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+ r.callback.onServiceStateChanged(
+ rawSs.createLocationInfoSanitizedCopy(true));
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -1142,9 +1144,9 @@
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
stateToSend = new ServiceState(state);
} else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.sanitizeLocationInfo(false);
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
} else {
- stateToSend = state.sanitizeLocationInfo(true);
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
}
if (DBG) {
log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index d19d2dd..c27b0da 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -16,8 +16,6 @@
package com.android.server;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -55,6 +53,7 @@
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/** @hide */
@@ -82,9 +81,9 @@
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
- mContext = checkNotNull(context, "missing Context");
- mNMS = checkNotNull(netManager, "missing INetworkManagementService");
- mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance");
+ mContext = Objects.requireNonNull(context, "missing Context");
+ mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
+ mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance");
}
/**
@@ -96,7 +95,7 @@
private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
enforceTestNetworkPermissions(mContext);
- checkNotNull(linkAddrs, "missing linkAddrs");
+ Objects.requireNonNull(linkAddrs, "missing linkAddrs");
String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
@@ -233,8 +232,8 @@
int callingUid,
@NonNull IBinder binder)
throws RemoteException, SocketException {
- checkNotNull(looper, "missing Looper");
- checkNotNull(context, "missing Context");
+ Objects.requireNonNull(looper, "missing Looper");
+ Objects.requireNonNull(context, "missing Context");
// iface and binder validity checked by caller
// Build network info with special testing type
@@ -267,7 +266,7 @@
// Find the currently assigned addresses, and add them to LinkProperties
boolean allowIPv4 = false, allowIPv6 = false;
NetworkInterface netIntf = NetworkInterface.getByName(iface);
- checkNotNull(netIntf, "No such network interface found: " + netIntf);
+ Objects.requireNonNull(netIntf, "No such network interface found: " + netIntf);
for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
lp.addLinkAddress(
@@ -305,8 +304,8 @@
@NonNull IBinder binder) {
enforceTestNetworkPermissions(mContext);
- checkNotNull(iface, "missing Iface");
- checkNotNull(binder, "missing IBinder");
+ Objects.requireNonNull(iface, "missing Iface");
+ Objects.requireNonNull(binder, "missing IBinder");
if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX)
|| iface.startsWith(TEST_TUN_PREFIX))) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5996b7d..a372fca0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -463,7 +463,7 @@
Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
callingUid, account.type);
@@ -544,7 +544,7 @@
@Override
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -590,8 +590,8 @@
@Override
public int getAccountVisibility(Account account, String packageName) {
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -659,7 +659,7 @@
*/
private Integer resolveAccountVisibility(Account account, @NonNull String packageName,
UserAccounts accounts) {
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
int uid = -1;
try {
long identityToken = clearCallingIdentity();
@@ -755,8 +755,8 @@
@Override
public boolean setAccountVisibility(Account account, String packageName, int newVisibility) {
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -1525,7 +1525,7 @@
+ ", caller's uid " + Binder.getCallingUid()
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
@@ -1563,8 +1563,8 @@
account, key, callingUid, Binder.getCallingPid());
Log.v(TAG, msg);
}
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(key, "key cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(key, "key cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -1715,7 +1715,7 @@
callingUid);
Log.v(TAG, msg);
}
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -2401,8 +2401,8 @@
@Override
public void invalidateAuthToken(String accountType, String authToken) {
int callerUid = Binder.getCallingUid();
- Preconditions.checkNotNull(accountType, "accountType cannot be null");
- Preconditions.checkNotNull(authToken, "authToken cannot be null");
+ Objects.requireNonNull(accountType, "accountType cannot be null");
+ Objects.requireNonNull(authToken, "authToken cannot be null");
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "invalidateAuthToken: accountType " + accountType
+ ", caller's uid " + callerUid
@@ -2518,8 +2518,8 @@
+ ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(authTokenType, "authTokenType cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(authTokenType, "authTokenType cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -2551,8 +2551,8 @@
+ ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(authTokenType, "authTokenType cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(authTokenType, "authTokenType cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -2578,7 +2578,7 @@
+ ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -2644,7 +2644,7 @@
+ ", caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
- Preconditions.checkNotNull(account, "account cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
String msg = String.format(
@@ -3946,9 +3946,9 @@
if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
throw new SecurityException("Can be called only by system UID");
}
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
- Preconditions.checkNotNull(userHandle, "userHandle cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(userHandle, "userHandle cannot be null");
final int userId = userHandle.getIdentifier();
@@ -4022,9 +4022,9 @@
throw new SecurityException("Can be called only by system UID");
}
- Preconditions.checkNotNull(account, "account cannot be null");
- Preconditions.checkNotNull(packageName, "packageName cannot be null");
- Preconditions.checkNotNull(userHandle, "userHandle cannot be null");
+ Objects.requireNonNull(account, "account cannot be null");
+ Objects.requireNonNull(packageName, "packageName cannot be null");
+ Objects.requireNonNull(userHandle, "userHandle cannot be null");
final int userId = userHandle.getIdentifier();
diff --git a/services/core/java/com/android/server/accounts/CryptoHelper.java b/services/core/java/com/android/server/accounts/CryptoHelper.java
index 2ade673..863d6b9 100644
--- a/services/core/java/com/android/server/accounts/CryptoHelper.java
+++ b/services/core/java/com/android/server/accounts/CryptoHelper.java
@@ -10,6 +10,7 @@
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
@@ -54,7 +55,7 @@
@NonNull
/* default */ Bundle encryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
- Preconditions.checkNotNull(bundle, "Cannot encrypt null bundle.");
+ Objects.requireNonNull(bundle, "Cannot encrypt null bundle.");
Parcel parcel = Parcel.obtain();
bundle.writeToParcel(parcel, 0);
byte[] clearBytes = parcel.marshall();
@@ -76,7 +77,7 @@
@Nullable
/* default */ Bundle decryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
- Preconditions.checkNotNull(bundle, "Cannot decrypt null bundle.");
+ Objects.requireNonNull(bundle, "Cannot decrypt null bundle.");
byte[] iv = bundle.getByteArray(KEY_IV);
byte[] encryptedBytes = bundle.getByteArray(KEY_CIPHER);
byte[] mac = bundle.getByteArray(KEY_MAC);
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
index 2af2f38..e38cf5f 100644
--- a/services/core/java/com/android/server/accounts/TokenCache.java
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -193,7 +193,7 @@
String packageName,
byte[] sigDigest,
long expiryMillis) {
- Preconditions.checkNotNull(account);
+ Objects.requireNonNull(account);
if (token == null || System.currentTimeMillis() > expiryMillis) {
return;
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 154d16f..a58bd9b 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -570,7 +570,7 @@
}
mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null,
- true);
+ true, false, null);
}
final ServiceMap smap = getServiceMapLocked(r.userId);
@@ -1395,7 +1395,7 @@
mAm.mAppOpsService.startOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
- null, true);
+ null, true, false, "");
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid, r.shortInstanceName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d7a46fe..dd1f370 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -324,6 +324,7 @@
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
@@ -3120,7 +3121,7 @@
private boolean hasUsageStatsPermission(String callingPackage) {
final int mode = mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS,
- Binder.getCallingUid(), callingPackage, null);
+ Binder.getCallingUid(), callingPackage, null, false, "");
if (mode == AppOpsManager.MODE_DEFAULT) {
return checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
== PackageManager.PERMISSION_GRANTED;
@@ -5816,7 +5817,8 @@
public int noteOp(String op, int uid, String packageName) {
// TODO moltmann: Allow to specify featureId
return mActivityManagerService.mAppOpsService
- .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName, null);
+ .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName, null,
+ false, "");
}
@Override
@@ -5968,7 +5970,7 @@
}
// ...and legacy apps get an AppOp check
int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
- uid, packageName, null);
+ uid, packageName, null, false, "");
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
}
@@ -19253,18 +19255,22 @@
@Override
public int noteOperation(int code, int uid, @Nullable String packageName,
- @Nullable String featureId,
- @NonNull QuadFunction<Integer, Integer, String, String, Integer> superImpl) {
+ @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+ @Nullable String message,
+ @NonNull HexFunction<Integer, Integer, String, String, Boolean, String, Integer>
+ superImpl) {
if (uid == mTargetUid && isTargetOp(code)) {
final long identity = Binder.clearCallingIdentity();
try {
return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
- "com.android.shell", null, uid, packageName, featureId);
+ "com.android.shell", null, uid, packageName, featureId,
+ shouldCollectAsyncNotedOp, message);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
- return superImpl.apply(code, uid, packageName, featureId);
+ return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
+ message);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 79fe610..a4c44fa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -111,6 +111,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -1785,7 +1786,7 @@
}
int runGetCurrentUser(PrintWriter pw) throws RemoteException {
- UserInfo currentUser = Preconditions.checkNotNull(mInterface.getCurrentUser(),
+ UserInfo currentUser = Objects.requireNonNull(mInterface.getCurrentUser(),
"Current user not set");
pw.println(currentUser.id);
return 0;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 10492a7..6fca3f6 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -650,7 +650,7 @@
// TODO moltmann: Set featureId from caller
if (opCode != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(opCode, r.callingUid,
- r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
+ r.callerPackage, null, false, "") != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
@@ -680,10 +680,10 @@
break;
}
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
- // TODO moltmann: Set componentId from caller
+ // TODO moltmann: Set featureId from caller
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.mAppOpsService.noteOperation(appOp,
- filter.receiverList.uid, filter.packageName, null)
+ filter.receiverList.uid, filter.packageName, null, false, "")
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
@@ -713,10 +713,10 @@
skip = true;
}
}
- // TODO moltmann: Set componentId from caller
+ // TODO moltmann: Set featureId from caller
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(r.appOp,
- filter.receiverList.uid, filter.packageName, null)
+ filter.receiverList.uid, filter.packageName, null, false, "")
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent.toString()
@@ -1370,10 +1370,10 @@
skip = true;
} else if (!skip && info.activityInfo.permission != null) {
final int opCode = AppOpsManager.permissionToOpCode(info.activityInfo.permission);
- // TODO moltmann: Set componentId from caller
+ // TODO moltmann: Set featureId from caller
if (opCode != AppOpsManager.OP_NONE
- && mService.mAppOpsService.noteOperation(opCode, r.callingUid,
- r.callerPackage, null) != AppOpsManager.MODE_ALLOWED) {
+ && mService.mAppOpsService.noteOperation(opCode, r.callingUid, r.callerPackage,
+ null, false, "") != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: broadcasting "
+ r.intent.toString()
+ " from " + r.callerPackage + " (pid="
@@ -1409,10 +1409,11 @@
break;
}
int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
- // TODO moltmann: Set componentId from caller
+ // TODO moltmann: Set featureId from caller
if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
&& mService.mAppOpsService.noteOperation(appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null,
+ false, "")
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
@@ -1426,10 +1427,11 @@
}
}
}
- // TODO moltmann: Set componentId from caller
+ // TODO moltmann: Set featureId from caller
if (!skip && r.appOp != AppOpsManager.OP_NONE
&& mService.mAppOpsService.noteOperation(r.appOp,
- info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null)
+ info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, null, false,
+ "")
!= AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "Appop Denial: receiving "
+ r.intent + " to "
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f9730a9..eb1ab38 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1723,7 +1723,7 @@
}
void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
- Preconditions.checkNotNull(name, "Observer name cannot be null");
+ Objects.requireNonNull(name, "Observer name cannot be null");
checkCallingPermission(INTERACT_ACROSS_USERS_FULL, "registerUserSwitchObserver");
mUserSwitchObservers.register(observer, name);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 9f23cdaf..5bbb517 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -18,7 +18,6 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.AppOpsManager.NoteOpEvent;
-import static android.app.AppOpsManager.OpEventProxyInfo;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
@@ -26,6 +25,7 @@
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OpEventProxyInfo;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -40,9 +40,12 @@
import static android.app.AppOpsManager.modeToName;
import static android.app.AppOpsManager.opToName;
import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import android.Manifest;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -69,6 +72,8 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
+import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
import android.database.ContentObserver;
import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
import android.net.Uri;
@@ -98,6 +103,7 @@
import android.util.KeyValueListParser;
import android.util.LongSparseArray;
import android.util.Pair;
+import android.util.Pools.SimplePool;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -122,6 +128,7 @@
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
+import com.android.server.SystemServerInitThreadPool;
import libcore.util.EmptyArray;
@@ -195,16 +202,26 @@
};
private static final int MAX_UNFORWARED_OPS = 10;
+ private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
Context mContext;
final AtomicFile mFile;
final Handler mHandler;
+ /** Pool for {@link OpEventProxyInfoPool} to avoid to constantly reallocate new objects */
+ @GuardedBy("this")
+ private final OpEventProxyInfoPool mOpEventProxyInfoPool = new OpEventProxyInfoPool();
+
+ /** Pool for {@link InProgressStartOpEventPool} to avoid to constantly reallocate new objects */
+ @GuardedBy("this")
+ private final InProgressStartOpEventPool mInProgressStartOpEventPool =
+ new InProgressStartOpEventPool();
+
private final AppOpsManagerInternalImpl mAppOpsManagerInternal
= new AppOpsManagerInternalImpl();
/**
- * Registered callbacks, called from {@link #noteAsyncOp}.
+ * Registered callbacks, called from {@link #collectAsyncNotedOp}.
*
* <p>(package name, uid) -> callbacks
*
@@ -215,7 +232,7 @@
mAsyncOpWatchers = new ArrayMap<>();
/**
- * Async note-ops collected from {@link #noteAsyncOp} that have not been delivered to a
+ * Async note-ops collected from {@link #collectAsyncNotedOp} that have not been delivered to a
* callback yet.
*
* <p>(package name, uid) -> list<ops>
@@ -266,6 +283,46 @@
private SparseArray<List<Integer>> mSwitchOpToOps;
/**
+ * An unsynchronized pool of {@link OpEventProxyInfo} objects.
+ */
+ private class OpEventProxyInfoPool extends SimplePool<OpEventProxyInfo> {
+ OpEventProxyInfoPool() {
+ super(MAX_UNUSED_POOLED_OBJECTS);
+ }
+
+ OpEventProxyInfo acquire(@IntRange(from = 0) int uid, @Nullable String packageName,
+ @Nullable String featureId) {
+ OpEventProxyInfo recycled = acquire();
+ if (recycled != null) {
+ recycled.reinit(uid, packageName, featureId);
+ return recycled;
+ }
+
+ return new OpEventProxyInfo(uid, packageName, featureId);
+ }
+ }
+
+ /**
+ * An unsynchronized pool of {@link InProgressStartOpEvent} objects.
+ */
+ private class InProgressStartOpEventPool extends SimplePool<InProgressStartOpEvent> {
+ InProgressStartOpEventPool() {
+ super(MAX_UNUSED_POOLED_OBJECTS);
+ }
+
+ InProgressStartOpEvent acquire(long startTime, long elapsedTime, @NonNull IBinder clientId,
+ @NonNull Runnable onDeath, int uidState) throws RemoteException {
+ InProgressStartOpEvent recycled = acquire();
+ if (recycled != null) {
+ recycled.reinit(startTime, elapsedTime, clientId, onDeath, uidState);
+ return recycled;
+ }
+
+ return new InProgressStartOpEvent(startTime, elapsedTime, clientId, onDeath, uidState);
+ }
+ }
+
+ /**
* 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
* holding the AppOpsService lock.
@@ -468,6 +525,9 @@
final UidState uidState;
final boolean isPrivileged;
+ /** Lazily populated cache of featureIds of this package */
+ final @NonNull ArraySet<String> knownFeatureIds = new ArraySet<>();
+
Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
packageName = _packageName;
uidState = _uidState;
@@ -477,39 +537,97 @@
/** A in progress startOp->finishOp event */
private static final class InProgressStartOpEvent implements IBinder.DeathRecipient {
- /** Time of startOp event */
- final long startTime;
+ /** Wall clock time of startOp event (not monotonic) */
+ private long mStartTime;
+
+ /** Elapsed time since boot of startOp event */
+ private long mStartElapsedTime;
/** Id of the client that started the event */
- final @NonNull IBinder clientId;
+ private @NonNull IBinder mClientId;
/** To call when client dies */
- final @NonNull Runnable onDeath;
+ private @NonNull Runnable mOnDeath;
/** uidstate used when calling startOp */
- final @AppOpsManager.UidState int uidState;
+ private @AppOpsManager.UidState int mUidState;
/** How many times the op was started but not finished yet */
int numUnfinishedStarts;
- private InProgressStartOpEvent(long startTime, @NonNull IBinder clientId,
- @NonNull Runnable onDeath, int uidState) throws RemoteException {
- this.startTime = startTime;
- this.clientId = clientId;
- this.onDeath = onDeath;
- this.uidState = uidState;
+ /**
+ * Create a new {@link InProgressStartOpEvent}.
+ *
+ * @param startTime The time {@link #startOperation} was called
+ * @param startElapsedTime The elapsed time when {@link #startOperation} was called
+ * @param clientId The client id of the caller of {@link #startOperation}
+ * @param onDeath The code to execute on client death
+ * @param uidState The uidstate of the app {@link #startOperation} was called for
+ *
+ * @throws RemoteException If the client is dying
+ */
+ private InProgressStartOpEvent(long startTime, long startElapsedTime,
+ @NonNull IBinder clientId, @NonNull Runnable onDeath, int uidState)
+ throws RemoteException {
+ mStartTime = startTime;
+ mStartElapsedTime = startElapsedTime;
+ mClientId = clientId;
+ mOnDeath = onDeath;
+ mUidState = uidState;
clientId.linkToDeath(this, 0);
}
/** Clean up event */
public void finish() {
- clientId.unlinkToDeath(this, 0);
+ mClientId.unlinkToDeath(this, 0);
}
@Override
public void binderDied() {
- onDeath.run();
+ mOnDeath.run();
+ }
+
+ /**
+ * Reinit existing object with new state.
+ *
+ * @param startTime The time {@link #startOperation} was called
+ * @param startElapsedTime The elapsed time when {@link #startOperation} was called
+ * @param clientId The client id of the caller of {@link #startOperation}
+ * @param onDeath The code to execute on client death
+ * @param uidState The uidstate of the app {@link #startOperation} was called for
+ *
+ * @throws RemoteException If the client is dying
+ */
+ public void reinit(long startTime, long startElapsedTime, @NonNull IBinder clientId,
+ @NonNull Runnable onDeath, int uidState) throws RemoteException {
+ mStartTime = startTime;
+ mStartElapsedTime = startElapsedTime;
+ mClientId = clientId;
+ mOnDeath = onDeath;
+ mUidState = uidState;
+
+ clientId.linkToDeath(this, 0);
+ }
+
+ /** @return Wall clock time of startOp event */
+ public long getStartTime() {
+ return mStartTime;
+ }
+
+ /** @return Elapsed time since boot of startOp event */
+ public long getStartElapsedTime() {
+ return mStartElapsedTime;
+ }
+
+ /** @return Id of the client that started the event */
+ public @NonNull IBinder getClientId() {
+ return mClientId;
+ }
+
+ /** @return uidstate used when calling startOp */
+ public int getUidState() {
+ return mUidState;
}
}
@@ -522,7 +640,7 @@
* <p>Key is {@link AppOpsManager#makeKey}
*/
@GuardedBy("AppOpsService.this")
- private @Nullable LongSparseArray<AppOpsManager.NoteOpEvent> mAccessEvents;
+ private @Nullable LongSparseArray<NoteOpEvent> mAccessEvents;
/**
* Last rejected accesses for each uidState/opFlag combination
@@ -530,7 +648,7 @@
* <p>Key is {@link AppOpsManager#makeKey}
*/
@GuardedBy("AppOpsService.this")
- private @Nullable LongSparseArray<AppOpsManager.NoteOpEvent> mRejectEvents;
+ private @Nullable LongSparseArray<NoteOpEvent> mRejectEvents;
/**
* Currently in progress startOp events
@@ -582,9 +700,16 @@
OpEventProxyInfo proxyInfo = null;
if (proxyUid != Process.INVALID_UID) {
- proxyInfo = new OpEventProxyInfo(proxyUid, proxyPackageName, proxyFeatureId);
+ proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
+ proxyFeatureId);
}
- mAccessEvents.put(key, new NoteOpEvent(noteTime, duration, proxyInfo));
+
+ NoteOpEvent existingEvent = mAccessEvents.get(key);
+ if (existingEvent != null) {
+ existingEvent.reinit(noteTime, duration, proxyInfo, mOpEventProxyInfoPool);
+ } else {
+ mAccessEvents.put(key, new NoteOpEvent(noteTime, duration, proxyInfo));
+ }
}
/**
@@ -613,7 +738,12 @@
}
// We do not collect proxy information for rejections yet
- mRejectEvents.put(key, new NoteOpEvent(noteTime, -1, null));
+ NoteOpEvent existingEvent = mRejectEvents.get(key);
+ if (existingEvent != null) {
+ existingEvent.reinit(noteTime, -1, null, mOpEventProxyInfoPool);
+ } else {
+ mRejectEvents.put(key, new NoteOpEvent(noteTime, -1, null));
+ }
}
/**
@@ -633,27 +763,15 @@
mInProgressEvents = new ArrayMap<>(1);
}
-
InProgressStartOpEvent event = mInProgressEvents.get(clientId);
if (event == null) {
- event = new InProgressStartOpEvent(System.currentTimeMillis(), clientId, () -> {
- // In the case the client dies without calling finish first
- synchronized (AppOpsService.this) {
- if (mInProgressEvents == null) {
- return;
- }
-
- InProgressStartOpEvent deadEvent = mInProgressEvents.get(clientId);
- if (deadEvent != null) {
- deadEvent.numUnfinishedStarts = 1;
- }
-
- finished(clientId);
- }
- }, uidState);
+ event = mInProgressStartOpEventPool.acquire(System.currentTimeMillis(),
+ SystemClock.elapsedRealtime(), clientId,
+ PooledLambda.obtainRunnable(AppOpsService::onClientDeath, this, clientId),
+ uidState);
mInProgressEvents.put(clientId, event);
} else {
- if (uidState != event.uidState) {
+ if (uidState != event.mUidState) {
onUidStateChanged(uidState);
}
}
@@ -697,13 +815,15 @@
}
// startOp events don't support proxy, hence use flags==SELF
- NoteOpEvent finishedEvent = new NoteOpEvent(event.startTime,
- System.currentTimeMillis() - event.startTime, null);
- mAccessEvents.put(makeKey(event.uidState, OP_FLAG_SELF), finishedEvent);
+ NoteOpEvent finishedEvent = new NoteOpEvent(event.getStartTime(),
+ SystemClock.elapsedRealtime() - event.getStartElapsedTime(), null);
+ mAccessEvents.put(makeKey(event.getUidState(), OP_FLAG_SELF), finishedEvent);
mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
- parent.packageName, event.uidState, AppOpsManager.OP_FLAG_SELF,
- finishedEvent.duration);
+ parent.packageName, event.getUidState(), AppOpsManager.OP_FLAG_SELF,
+ finishedEvent.getDuration());
+
+ mInProgressStartOpEventPool.release(event);
if (mInProgressEvents.isEmpty()) {
mInProgressEvents = null;
@@ -718,6 +838,26 @@
}
/**
+ * Called in the case the client dies without calling finish first
+ *
+ * @param clientId The client that died
+ */
+ void onClientDeath(@NonNull IBinder clientId) {
+ synchronized (AppOpsService.this) {
+ if (mInProgressEvents == null) {
+ return;
+ }
+
+ InProgressStartOpEvent deadEvent = mInProgressEvents.get(clientId);
+ if (deadEvent != null) {
+ deadEvent.numUnfinishedStarts = 1;
+ }
+
+ finished(clientId);
+ }
+ }
+
+ /**
* Notify that the state of the uid changed
*
* @param newState The new state
@@ -731,10 +871,10 @@
for (int i = 0; i < numInProgressEvents; i++) {
InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
- if (event.uidState != newState) {
+ if (event.getUidState() != newState) {
try {
- finished(event.clientId, false);
- started(event.clientId, newState);
+ finished(event.getClientId(), false);
+ started(event.getClientId(), newState);
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "Cannot switch to new uidState " + newState);
}
@@ -742,6 +882,59 @@
}
}
+ /**
+ * Combine {@code a} and {@code b} and return the result. The result might be {@code a}
+ * or {@code b}. If there is an event for the same key in both the later event is retained.
+ */
+ private @Nullable LongSparseArray<NoteOpEvent> add(@Nullable LongSparseArray<NoteOpEvent> a,
+ @Nullable LongSparseArray<NoteOpEvent> b) {
+ if (a == null) {
+ return b;
+ }
+
+ if (b == null) {
+ return a;
+ }
+
+ int numEventsToAdd = b.size();
+ for (int i = 0; i < numEventsToAdd; i++) {
+ long keyOfEventToAdd = b.keyAt(i);
+ NoteOpEvent bEvent = b.valueAt(i);
+ NoteOpEvent aEvent = a.get(keyOfEventToAdd);
+
+ if (aEvent == null || bEvent.getNoteTime() > aEvent.getNoteTime()) {
+ a.put(keyOfEventToAdd, bEvent);
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Add all data from the {@code featureToAdd} to this op.
+ *
+ * <p>If there is an event for the same key in both the later event is retained.
+ * <p>{@code opToAdd} should not be used after this method is called.
+ *
+ * @param opToAdd The op to add
+ */
+ public void add(@NonNull FeatureOp opToAdd) {
+ if (opToAdd.mInProgressEvents != null) {
+ Slog.w(TAG, "Ignoring " + opToAdd.mInProgressEvents.size() + " running app-ops");
+
+ int numInProgressEvents = opToAdd.mInProgressEvents.size();
+ for (int i = 0; i < numInProgressEvents; i++) {
+ InProgressStartOpEvent event = opToAdd.mInProgressEvents.valueAt(i);
+
+ event.finish();
+ mInProgressStartOpEventPool.release(event);
+ }
+ }
+
+ mAccessEvents = add(mAccessEvents, opToAdd.mAccessEvents);
+ mRejectEvents = add(mRejectEvents, opToAdd.mRejectEvents);
+ }
+
public boolean isRunning() {
return mInProgressEvents != null;
}
@@ -751,15 +944,30 @@
|| (mRejectEvents != null && mRejectEvents.size() > 0);
}
- @NonNull OpFeatureEntry createFeatureEntryLocked() {
- LongSparseArray<NoteOpEvent> accessEvents = null;
- if (mAccessEvents != null) {
- accessEvents = mAccessEvents.clone();
+ /**
+ * Clone a {@link LongSparseArray} and clone all values.
+ */
+ private @Nullable LongSparseArray<NoteOpEvent> deepClone(
+ @Nullable LongSparseArray<NoteOpEvent> original) {
+ if (original == null) {
+ return original;
}
+ int size = original.size();
+ LongSparseArray<NoteOpEvent> clone = new LongSparseArray<>(size);
+ for (int i = 0; i < size; i++) {
+ clone.put(original.keyAt(i), new NoteOpEvent(original.valueAt(i)));
+ }
+
+ return clone;
+ }
+
+ @NonNull OpFeatureEntry createFeatureEntryLocked() {
+ LongSparseArray<NoteOpEvent> accessEvents = deepClone(mAccessEvents);
+
// Add in progress events as access events
if (mInProgressEvents != null) {
- long now = System.currentTimeMillis();
+ long now = SystemClock.elapsedRealtime();
int numInProgressEvents = mInProgressEvents.size();
if (accessEvents == null) {
@@ -770,15 +978,13 @@
InProgressStartOpEvent event = mInProgressEvents.valueAt(i);
// startOp events don't support proxy
- accessEvents.append(makeKey(event.uidState, OP_FLAG_SELF),
- new NoteOpEvent(event.startTime, now - event.startTime, null));
+ accessEvents.append(makeKey(event.getUidState(), OP_FLAG_SELF),
+ new NoteOpEvent(event.getStartTime(), now - event.getStartElapsedTime(),
+ null));
}
}
- LongSparseArray<NoteOpEvent> rejectEvents = null;
- if (mRejectEvents != null) {
- rejectEvents = mRejectEvents.clone();
- }
+ LongSparseArray<NoteOpEvent> rejectEvents = deepClone(mRejectEvents);
return new OpFeatureEntry(parent.op, isRunning(), accessEvents, rejectEvents);
}
@@ -1018,6 +1224,13 @@
}
}
+ /**
+ * Call {@link FeatureOp#onClientDeath featureOp.onClientDeath(clientId)}.
+ */
+ private static void onClientDeath(@NonNull FeatureOp featureOp, @NonNull IBinder clientId) {
+ featureOp.onClientDeath(clientId);
+ }
+
public AppOpsService(File storagePath, Handler handler) {
LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
mFile = new AtomicFile(storagePath, "appops");
@@ -1032,20 +1245,110 @@
LocalServices.addService(AppOpsManagerInternal.class, mAppOpsManagerInternal);
}
+ /** Handler for work when packages are removed or updated */
+ private BroadcastReceiver mOnPackageUpdatedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ String pkgName = intent.getData().getEncodedSchemeSpecificPart();
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID);
+
+ if (action.equals(ACTION_PACKAGE_REMOVED) && !intent.hasExtra(EXTRA_REPLACING)) {
+ synchronized (AppOpsService.this) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null || uidState.pkgOps == null) {
+ return;
+ }
+
+ Ops removedOps = uidState.pkgOps.remove(pkgName);
+ if (removedOps != null) {
+ scheduleFastWriteLocked();
+ }
+ }
+ } else if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) {
+ AndroidPackage pkg = LocalServices.getService(
+ PackageManagerInternal.class).getPackage(pkgName);
+ if (pkg == null) {
+ return;
+ }
+
+ ArrayMap<String, String> dstFeatureIds = new ArrayMap<>();
+ ArraySet<String> featureIds = new ArraySet<>();
+ if (pkg.getFeatures() != null) {
+ int numFeatures = pkg.getFeatures().size();
+ for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+ ParsedFeature feature = pkg.getFeatures().get(featureNum);
+ featureIds.add(feature.id);
+
+ int numInheritFrom = feature.inheritFrom.size();
+ for (int inheritFromNum = 0; inheritFromNum < numInheritFrom;
+ inheritFromNum++) {
+ dstFeatureIds.put(feature.inheritFrom.get(inheritFromNum),
+ feature.id);
+ }
+ }
+ }
+
+ synchronized (AppOpsService.this) {
+ UidState uidState = mUidStates.get(uid);
+ if (uidState == null || uidState.pkgOps == null) {
+ return;
+ }
+
+ Ops ops = uidState.pkgOps.get(pkgName);
+ if (ops == null) {
+ return;
+ }
+
+ ops.knownFeatureIds.clear();
+ int numOps = ops.size();
+ for (int opNum = 0; opNum < numOps; opNum++) {
+ Op op = ops.valueAt(opNum);
+
+ int numFeatures = op.mFeatures.size();
+ for (int featureNum = numFeatures - 1; featureNum >= 0; featureNum--) {
+ String featureId = op.mFeatures.keyAt(featureNum);
+
+ if (featureIds.contains(featureId)) {
+ // feature still exist after upgrade
+ continue;
+ }
+
+ String newFeatureId = dstFeatureIds.get(featureId);
+
+ FeatureOp newFeatureOp = op.getOrCreateFeature(op, newFeatureId);
+ newFeatureOp.add(op.mFeatures.valueAt(featureNum));
+ op.mFeatures.removeAt(featureNum);
+
+ scheduleFastWriteLocked();
+ }
+ }
+ }
+ }
+ }
+ };
+
public void systemReady() {
mConstants.startMonitoring(mContext.getContentResolver());
mHistoricalRegistry.systemReady(mContext.getContentResolver());
- synchronized (this) {
- boolean changed = false;
- for (int i = mUidStates.size() - 1; i >= 0; i--) {
- UidState uidState = mUidStates.valueAt(i);
+ IntentFilter packageUpdateFilter = new IntentFilter();
+ packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ packageUpdateFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ packageUpdateFilter.addDataScheme("package");
- String[] packageNames = getPackagesForUid(uidState.uid);
- if (ArrayUtils.isEmpty(packageNames)) {
+ mContext.registerReceiver(mOnPackageUpdatedReceiver, packageUpdateFilter);
+
+ synchronized (this) {
+ for (int uidNum = mUidStates.size() - 1; uidNum >= 0; uidNum--) {
+ int uid = mUidStates.keyAt(uidNum);
+ UidState uidState = mUidStates.valueAt(uidNum);
+
+ String[] pkgsInUid = getPackagesForUid(uidState.uid);
+ if (ArrayUtils.isEmpty(pkgsInUid)) {
uidState.clear();
- mUidStates.removeAt(i);
- changed = true;
+ mUidStates.removeAt(uidNum);
+ scheduleFastWriteLocked();
continue;
}
@@ -1054,31 +1357,24 @@
continue;
}
- Iterator<Ops> it = pkgs.values().iterator();
- while (it.hasNext()) {
- Ops ops = it.next();
- int curUid = -1;
- try {
- curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES,
- UserHandle.getUserId(ops.uidState.uid));
- } catch (RemoteException ignored) {
- }
- if (curUid != ops.uidState.uid) {
- Slog.i(TAG, "Pruning old package " + ops.packageName
- + "/" + ops.uidState + ": new uid=" + curUid);
- it.remove();
- changed = true;
- }
- }
+ int numPkgs = pkgs.size();
+ for (int pkgNum = 0; pkgNum < numPkgs; pkgNum++) {
+ String pkg = pkgs.keyAt(pkgNum);
- if (uidState.isDefault()) {
- mUidStates.removeAt(i);
+ String action;
+ if (!ArrayUtils.contains(pkgsInUid, pkg)) {
+ action = Intent.ACTION_PACKAGE_REMOVED;
+ } else {
+ action = Intent.ACTION_PACKAGE_REPLACED;
+ }
+
+ SystemServerInitThreadPool.submit(
+ () -> mOnPackageUpdatedReceiver.onReceive(mContext, new Intent(action)
+ .setData(Uri.fromParts("package", pkg, null))
+ .putExtra(Intent.EXTRA_UID, uid)),
+ "Update app-ops uidState in case package " + pkg + " changed");
}
}
- if (changed) {
- scheduleFastWriteLocked();
- }
}
final IntentFilter packageSuspendFilter = new IntentFilter();
@@ -1140,11 +1436,13 @@
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
- packageName, null) != AppOpsManager.MODE_ALLOWED) {
+ packageName, null, true, "External storage policy")
+ != AppOpsManager.MODE_ALLOWED) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
- packageName, null) != AppOpsManager.MODE_ALLOWED) {
+ packageName, null, true, "External storage policy")
+ != AppOpsManager.MODE_ALLOWED) {
return Zygote.MOUNT_EXTERNAL_READ;
}
return Zygote.MOUNT_EXTERNAL_WRITE;
@@ -1192,7 +1490,7 @@
FeatureOp featureOp = op.mFeatures.valueAt(featureNum);
while (featureOp.mInProgressEvents != null) {
- featureOp.mInProgressEvents.valueAt(0).onDeath.run();
+ featureOp.finished(featureOp.mInProgressEvents.keyAt(0));
}
}
}
@@ -1382,7 +1680,7 @@
return Collections.emptyList();
}
synchronized (this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false /* isPrivileged */,
+ Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, null, false /* isPrivileged */,
false /* edit */);
if (pkgOps == null) {
return null;
@@ -1411,7 +1709,7 @@
.setOpNames(opNames)
.setFlags(flags)
.build();
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
@@ -1436,7 +1734,7 @@
.setOpNames(opNames)
.setFlags(flags)
.build();
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
@@ -1482,7 +1780,7 @@
op.removeFeaturesWithNoTime();
if (op.mFeatures.size() == 0) {
- Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */,
+ Ops ops = getOpsRawLocked(uid, packageName, null, false /* isPrivileged */,
false /* edit */);
if (ops != null) {
ops.remove(op.op);
@@ -1746,7 +2044,7 @@
boolean isPrivileged;
try {
- isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName, null);
} catch (SecurityException e) {
Slog.e(TAG, "Cannot setMode", e);
return;
@@ -1761,7 +2059,7 @@
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
- Op op = getOpLocked(code, uid, packageName, isPrivileged, true);
+ Op op = getOpLocked(code, uid, packageName, null, isPrivileged, true);
if (op != null) {
if (op.mode != mode) {
op.mode = mode;
@@ -2131,7 +2429,7 @@
boolean isPrivileged;
try {
- isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName, null);
} catch (SecurityException e) {
Slog.e(TAG, "checkOperation", e);
return AppOpsManager.opToDefaultMode(code);
@@ -2141,7 +2439,7 @@
return AppOpsManager.MODE_IGNORED;
}
synchronized (this) {
- if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
+ if (isOpRestrictedLocked(uid, code, packageName, null, isPrivileged)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -2151,7 +2449,7 @@
final int rawMode = uidState.opModes.get(code);
return raw ? rawMode : uidState.evalMode(code, rawMode);
}
- Op op = getOpLocked(code, uid, packageName, false, false);
+ Op op = getOpLocked(code, uid, packageName, null, false, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -2212,9 +2510,9 @@
@Override
public int checkPackage(int uid, String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
try {
- verifyAndGetIsPrivileged(uid, packageName);
+ verifyAndGetIsPrivileged(uid, packageName, null);
return AppOpsManager.MODE_ALLOWED;
} catch (SecurityException ignored) {
@@ -2225,7 +2523,7 @@
@Override
public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedFeatureId, int proxyUid, String proxyPackageName,
- String proxyFeatureId) {
+ String proxyFeatureId, boolean shouldCollectAsyncNotedOp, String message) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
@@ -2241,7 +2539,8 @@
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
- proxyFeatureId, Process.INVALID_UID, null, null, proxyFlags);
+ proxyFeatureId, Process.INVALID_UID, null, null, proxyFlags,
+ !isProxyTrusted, "proxy " + message);
if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
return proxyMode;
}
@@ -2254,23 +2553,27 @@
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
proxiedFeatureId, proxyUid, resolveProxyPackageName, proxyFeatureId,
- proxiedFlags);
+ proxiedFlags, shouldCollectAsyncNotedOp, message);
}
@Override
- public int noteOperation(int code, int uid, String packageName, String featureId) {
+ public int noteOperation(int code, int uid, String packageName, String featureId,
+ boolean shouldCollectAsyncNotedOp, String message) {
final CheckOpsDelegate delegate;
synchronized (this) {
delegate = mCheckOpsDelegate;
}
if (delegate == null) {
- return noteOperationImpl(code, uid, packageName, featureId);
+ return noteOperationImpl(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
+ message);
}
- return delegate.noteOperation(code, uid, packageName, featureId,
- AppOpsService.this::noteOperationImpl);
+ return delegate.noteOperation(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
+ message, AppOpsService.this::noteOperationImpl);
}
- private int noteOperationImpl(int code, int uid, String packageName, String featureId) {
+ private int noteOperationImpl(int code, int uid, @Nullable String packageName,
+ @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+ @Nullable String message) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2278,24 +2581,25 @@
return AppOpsManager.MODE_IGNORED;
}
return noteOperationUnchecked(code, uid, resolvedPackageName, featureId,
- Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF);
+ Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF,
+ shouldCollectAsyncNotedOp, message);
}
- private int noteOperationUnchecked(int code, int uid, String packageName, String featureId,
- int proxyUid, String proxyPackageName, @Nullable String proxyFeatureId,
- @OpFlags int flags) {
- // TODO moltmann: Verify that feature is declared in package
-
+ private int noteOperationUnchecked(int code, int uid, @NonNull String packageName,
+ @Nullable String featureId, int proxyUid, String proxyPackageName,
+ @Nullable String proxyFeatureId, @OpFlags int flags, boolean shouldCollectAsyncNotedOp,
+ @Nullable String message) {
boolean isPrivileged;
try {
- isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName, featureId);
} catch (SecurityException e) {
Slog.e(TAG, "noteOperation", e);
return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
- final Ops ops = getOpsRawLocked(uid, packageName, isPrivileged, true /* edit */);
+ final Ops ops = getOpsRawLocked(uid, packageName, featureId, isPrivileged,
+ true /* edit */);
if (ops == null) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
@@ -2303,9 +2607,9 @@
+ " package " + packageName);
return AppOpsManager.MODE_ERRORED;
}
- final Op op = getOpLocked(ops, code, true);
+ final Op op = getOpLocked(ops, code, uid, true);
final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
- if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
+ if (isOpRestrictedLocked(uid, code, packageName, featureId, isPrivileged)) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
return AppOpsManager.MODE_IGNORED;
@@ -2314,7 +2618,7 @@
if (featureOp.isRunning()) {
Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
+ code + " startTime of in progress event="
- + featureOp.mInProgressEvents.valueAt(0).startTime);
+ + featureOp.mInProgressEvents.valueAt(0).getStartTime());
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -2333,7 +2637,8 @@
return uidMode;
}
} else {
- final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+ final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true)
+ : op;
final int mode = switchOp.evalMode();
if (mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
@@ -2354,6 +2659,11 @@
uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_ALLOWED);
+
+ if (shouldCollectAsyncNotedOp) {
+ collectAsyncNotedOp(uid, packageName, code, featureId, message);
+ }
+
return AppOpsManager.MODE_ALLOWED;
}
}
@@ -2419,7 +2729,7 @@
Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty");
Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1,
"Invalid op code in: " + Arrays.toString(ops));
- Preconditions.checkNotNull(callback, "Callback cannot be null");
+ Objects.requireNonNull(callback, "Callback cannot be null");
synchronized (this) {
SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder());
if (callbacks == null) {
@@ -2436,7 +2746,7 @@
@Override
public void stopWatchingNoted(IAppOpsNotedCallback callback) {
- Preconditions.checkNotNull(callback, "Callback cannot be null");
+ Objects.requireNonNull(callback, "Callback cannot be null");
synchronized (this) {
final SparseArray<NotedCallback> notedCallbacks =
mNotedWatchers.remove(callback.asBinder());
@@ -2450,21 +2760,20 @@
}
}
- @Override
- public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
- String featureId, String message) {
- Preconditions.checkNotNull(message);
- verifyAndGetIsPrivileged(uid, packageName);
-
- verifyIncomingUid(uid);
- verifyIncomingOp(opCode);
+ /**
+ * Collect an {@link AsyncNotedAppOp}.
+ *
+ * @param uid The uid the op was noted for
+ * @param packageName The package the op was noted for
+ * @param opCode The code of the op noted
+ * @param featureId The id of the feature to op was noted for
+ * @param message The message for the op noting
+ */
+ private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode,
+ @Nullable String featureId, @NonNull String message) {
+ Objects.requireNonNull(message);
int callingUid = Binder.getCallingUid();
- long now = System.currentTimeMillis();
-
- if (callingPackageName != null) {
- verifyAndGetIsPrivileged(callingUid, callingPackageName);
- }
long token = Binder.clearCallingIdentity();
try {
@@ -2473,7 +2782,7 @@
RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
- callingPackageName, featureId, message, now);
+ featureId, message, System.currentTimeMillis());
final boolean[] wasNoteForwarded = {false};
if (callbacks != null) {
@@ -2522,13 +2831,13 @@
@Override
public void startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(callback);
int uid = Binder.getCallingUid();
Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
- verifyAndGetIsPrivileged(uid, packageName);
+ verifyAndGetIsPrivileged(uid, packageName, null);
synchronized (this) {
RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
@@ -2552,13 +2861,13 @@
@Override
public void stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(callback);
int uid = Binder.getCallingUid();
Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
- verifyAndGetIsPrivileged(uid, packageName);
+ verifyAndGetIsPrivileged(uid, packageName, null);
synchronized (this) {
RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
@@ -2573,11 +2882,11 @@
@Override
public List<AsyncNotedAppOp> extractAsyncOps(String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
int uid = Binder.getCallingUid();
- verifyAndGetIsPrivileged(uid, packageName);
+ verifyAndGetIsPrivileged(uid, packageName, null);
synchronized (this) {
return mUnforwardedAsyncNotedOps.remove(getAsyncNotedOpsKey(packageName, uid));
@@ -2586,7 +2895,8 @@
@Override
public int startOperation(IBinder clientId, int code, int uid, String packageName,
- String featureId, boolean startIfModeDefault) {
+ String featureId, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
+ String message) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -2596,22 +2906,22 @@
boolean isPrivileged;
try {
- isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName, featureId);
} catch (SecurityException e) {
Slog.e(TAG, "startOperation", e);
return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
- final Ops ops = getOpsRawLocked(uid, resolvedPackageName, isPrivileged,
+ final Ops ops = getOpsRawLocked(uid, resolvedPackageName, featureId, isPrivileged,
true /* edit */);
if (ops == null) {
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
+ " package " + resolvedPackageName);
return AppOpsManager.MODE_ERRORED;
}
- final Op op = getOpLocked(ops, code, true);
- if (isOpRestrictedLocked(uid, code, resolvedPackageName, isPrivileged)) {
+ final Op op = getOpLocked(ops, code, uid, true);
+ if (isOpRestrictedLocked(uid, code, resolvedPackageName, featureId, isPrivileged)) {
return AppOpsManager.MODE_IGNORED;
}
final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
@@ -2633,7 +2943,8 @@
return uidMode;
}
} else {
- final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
+ final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true)
+ : op;
final int mode = switchOp.evalMode();
if (mode != AppOpsManager.MODE_ALLOWED
&& (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
@@ -2656,6 +2967,10 @@
}
}
+ if (shouldCollectAsyncNotedOp) {
+ collectAsyncNotedOp(uid, packageName, code, featureId, message);
+ }
+
return AppOpsManager.MODE_ALLOWED;
}
@@ -2671,14 +2986,14 @@
boolean isPrivileged;
try {
- isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName, featureId);
} catch (SecurityException e) {
Slog.e(TAG, "Cannot finishOperation", e);
return;
}
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, isPrivileged, true);
+ Op op = getOpLocked(code, uid, resolvedPackageName, featureId, isPrivileged, true);
if (op == null) {
return;
}
@@ -2909,22 +3224,24 @@
*
* @param uid The uid the package belongs to
* @param packageName The package the might belong to the uid
+ * @param featureId The feature in the package or {@code null} if no need to verify
*
* @return {@code true} iff the package is privileged
*/
- private boolean verifyAndGetIsPrivileged(int uid, String packageName) {
+ private boolean verifyAndGetIsPrivileged(int uid, String packageName,
+ @Nullable String featureId) {
if (uid == Process.ROOT_UID) {
// For backwards compatibility, don't check package name for root UID.
return false;
}
- // Do not check if uid/packageName is already known
+ // Do not check if uid/packageName/featureId is already known
synchronized (this) {
UidState uidState = mUidStates.get(uid);
if (uidState != null && uidState.pkgOps != null) {
Ops ops = uidState.pkgOps.get(packageName);
- if (ops != null) {
+ if (ops != null && (featureId == null || ops.knownFeatureIds.contains(featureId))) {
return ops.isPrivileged;
}
}
@@ -2934,19 +3251,31 @@
final long ident = Binder.clearCallingIdentity();
try {
int pkgUid;
+ AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class).getPackage(
+ packageName);
+ boolean isFeatureIdValid = false;
- ApplicationInfo appInfo = LocalServices.getService(PackageManagerInternal.class)
- .getApplicationInfo(packageName, PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
- | PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_INSTANT,
- Process.SYSTEM_UID, UserHandle.getUserId(uid));
- if (appInfo != null) {
- pkgUid = appInfo.uid;
- isPrivileged = (appInfo.privateFlags
- & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+ if (pkg != null) {
+ if (featureId == null) {
+ isFeatureIdValid = true;
+ } else {
+ if (pkg.getFeatures() != null) {
+ int numFeatures = pkg.getFeatures().size();
+ for (int i = 0; i < numFeatures; i++) {
+ if (pkg.getFeatures().get(i).id.equals(featureId)) {
+ isFeatureIdValid = true;
+ }
+ }
+ }
+ }
+
+ pkgUid = UserHandle.getUid(
+ UserHandle.getUserId(uid), UserHandle.getAppId(pkg.getUid()));
+ isPrivileged = pkg.isPrivileged();
} else {
+ // Allow any feature id for resolvable uids
+ isFeatureIdValid = true;
+
pkgUid = resolveUid(packageName);
if (pkgUid >= 0) {
isPrivileged = false;
@@ -2956,6 +3285,12 @@
throw new SecurityException("Specified package " + packageName + " under uid " + uid
+ " but it is really " + pkgUid);
}
+
+ if (!isFeatureIdValid) {
+ // TODO moltmann: Switch from logging to enforcement
+ Slog.e(TAG, "featureId " + featureId + " not declared in manifest of "
+ + packageName);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2968,12 +3303,14 @@
*
* @param uid The uid the package belongs to
* @param packageName The name of the package
+ * @param featureId The feature in the package
* @param isPrivileged If the package is privilidged (ignored if {@code edit} is false)
* @param edit If an ops does not exist, create the ops?
* @return
*/
- private Ops getOpsRawLocked(int uid, String packageName, boolean isPrivileged, boolean edit) {
+ private Ops getOpsRawLocked(int uid, String packageName, @Nullable String featureId,
+ boolean isPrivileged, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
return null;
@@ -2994,6 +3331,9 @@
ops = new Ops(packageName, uidState, isPrivileged);
uidState.pkgOps.put(packageName, ops);
}
+ if (edit && featureId != null) {
+ ops.knownFeatureIds.add(featureId);
+ }
return ops;
}
@@ -3004,13 +3344,14 @@
*
* @param uid The uid the of the package
* @param packageName The package name for which to get the state for
+ * @param featureId The feature in the package
* @param edit Iff {@code true} create the {@link Ops} object if not yet created
* @param isPrivileged Whether the package is privileged or not
*
* @return The {@link Ops state} of all ops for the package
*/
private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
- boolean edit, boolean isPrivileged) {
+ @Nullable String featureId, boolean edit, boolean isPrivileged) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
return null;
@@ -3031,6 +3372,11 @@
ops = new Ops(packageName, uidState, isPrivileged);
uidState.pkgOps.put(packageName, ops);
}
+
+ if (edit && featureId != null) {
+ ops.knownFeatureIds.add(featureId);
+ }
+
return ops;
}
@@ -3056,6 +3402,7 @@
* @param code The code of the op
* @param uid The uid the of the package
* @param packageName The package name for which to get the state for
+ * @param featureId The feature in the package
* @param isPrivileged Whether the package is privileged or not (only used if {@code edit
* == true})
* @param edit Iff {@code true} create the {@link Op} object if not yet created
@@ -3063,21 +3410,21 @@
* @return The {@link Op state} of the op
*/
private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName,
- boolean isPrivileged, boolean edit) {
- Ops ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
+ @Nullable String featureId, boolean isPrivileged, boolean edit) {
+ Ops ops = getOpsRawNoVerifyLocked(uid, packageName, featureId, edit, isPrivileged);
if (ops == null) {
return null;
}
- return getOpLocked(ops, code, edit);
+ return getOpLocked(ops, code, uid, edit);
}
- private Op getOpLocked(Ops ops, int code, boolean edit) {
+ private Op getOpLocked(Ops ops, int code, int uid, boolean edit) {
Op op = ops.get(code);
if (op == null) {
if (!edit) {
return null;
}
- op = new Op(ops.uidState, ops.packageName, code, ops.uidState.uid);
+ op = new Op(ops.uidState, ops.packageName, code, uid);
ops.put(code, op);
}
if (edit) {
@@ -3095,7 +3442,7 @@
}
private boolean isOpRestrictedLocked(int uid, int code, String packageName,
- boolean isPrivileged) {
+ @Nullable String featureId, boolean isPrivileged) {
int userHandle = UserHandle.getUserId(uid);
final int restrictionSetCount = mOpUserRestrictions.size();
@@ -3107,7 +3454,7 @@
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, isPrivileged,
+ Ops ops = getOpsRawLocked(uid, packageName, featureId, isPrivileged,
true /* edit */);
if ((ops != null) && ops.isPrivileged) {
return false;
@@ -3484,7 +3831,7 @@
out.startTag(null, "uid");
out.attribute(null, "n", Integer.toString(pkg.getUid()));
synchronized (this) {
- Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(),
+ Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), null,
false /* isPrivileged */, false /* edit */);
// Should always be present as the list of PackageOps is generated
// from Ops.
@@ -4050,7 +4397,8 @@
if (shell.packageName != null) {
shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
- shell.packageName, shell.featureId, true);
+ shell.packageName, shell.featureId, true, true,
+ "appops start shell command");
} else {
return -1;
}
@@ -4188,18 +4536,18 @@
final FeatureOp featureOp = op.mFeatures.get(featureId);
if (featureOp.isRunning()) {
- long earliestStartTime = Long.MAX_VALUE;
+ long earliestElapsedTime = Long.MAX_VALUE;
long maxNumStarts = 0;
int numInProgressEvents = featureOp.mInProgressEvents.size();
for (int i = 0; i < numInProgressEvents; i++) {
InProgressStartOpEvent event = featureOp.mInProgressEvents.valueAt(i);
- earliestStartTime = Math.min(earliestStartTime, event.startTime);
+ earliestElapsedTime = Math.min(earliestElapsedTime, event.getStartElapsedTime());
maxNumStarts = Math.max(maxNumStarts, event.numUnfinishedStarts);
}
pw.print(prefix + "Running start at: ");
- TimeUtils.formatDuration(nowElapsed - earliestStartTime, pw);
+ TimeUtils.formatDuration(nowElapsed - earliestElapsedTime, pw);
pw.println();
if (maxNumStarts > 1) {
@@ -4471,7 +4819,7 @@
if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
boolean hasOp = dumpOp < 0 || (uidState.opModes != null
&& uidState.opModes.indexOfKey(dumpOp) >= 0);
- boolean hasPackage = dumpPackage == null;
+ boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i);
boolean hasMode = dumpMode < 0;
if (!hasMode && opModes != null) {
for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
@@ -4702,8 +5050,8 @@
@Override
public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
checkSystemUid("setUserRestrictions");
- Preconditions.checkNotNull(restrictions);
- Preconditions.checkNotNull(token);
+ Objects.requireNonNull(restrictions);
+ Objects.requireNonNull(token);
for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
String restriction = AppOpsManager.opToRestriction(i);
if (restriction != null) {
@@ -4730,7 +5078,7 @@
}
}
verifyIncomingOp(code);
- Preconditions.checkNotNull(token);
+ Objects.requireNonNull(token);
setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
}
@@ -4801,7 +5149,7 @@
}
// TODO moltmann: Allow to check for feature op activeness
synchronized (AppOpsService.this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false, false);
+ Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, null, false, false);
if (pkgOps == null) {
return false;
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index fc67e24..5ac5b29 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -67,6 +67,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* An attention service implementation that runs in System Server process.
@@ -120,7 +121,7 @@
AttentionManagerService(Context context, PowerManager powerManager, Object lock,
AttentionHandler handler) {
super(context);
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mPowerManager = powerManager;
mLock = lock;
mAttentionHandler = handler;
@@ -200,7 +201,7 @@
*/
@VisibleForTesting
boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
- Preconditions.checkNotNull(callbackInternal);
+ Objects.requireNonNull(callbackInternal);
if (!isAttentionServiceSupported()) {
Slog.w(LOG_TAG, "Trying to call checkAttention() on an unsupported device.");
@@ -543,9 +544,9 @@
UserState(int userId, Context context, Object lock, Handler handler,
ComponentName componentName) {
mUserId = userId;
- mContext = Preconditions.checkNotNull(context);
- mLock = Preconditions.checkNotNull(lock);
- mComponentName = Preconditions.checkNotNull(componentName);
+ mContext = Objects.requireNonNull(context);
+ mLock = Objects.requireNonNull(lock);
+ mComponentName = Objects.requireNonNull(componentName);
mAttentionHandler = handler;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 114aac9..bc4dc8f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2196,7 +2196,7 @@
public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags,
String callingPackage) {
enforceModifyAudioRoutingPermission();
- Preconditions.checkNotNull(attr, "attr must not be null");
+ Objects.requireNonNull(attr, "attr must not be null");
// @todo not hold the caller context, post message
int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
final int device = getDeviceForStream(stream);
@@ -2231,7 +2231,7 @@
/** @see AudioManager#getVolumeIndexForAttributes(attr) */
public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
enforceModifyAudioRoutingPermission();
- Preconditions.checkNotNull(attr, "attr must not be null");
+ Objects.requireNonNull(attr, "attr must not be null");
int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
final int device = getDeviceForStream(stream);
@@ -2241,14 +2241,14 @@
/** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
enforceModifyAudioRoutingPermission();
- Preconditions.checkNotNull(attr, "attr must not be null");
+ Objects.requireNonNull(attr, "attr must not be null");
return AudioSystem.getMaxVolumeIndexForAttributes(attr);
}
/** @see AudioManager#getMinVolumeIndexForAttributes(attr) */
public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
enforceModifyAudioRoutingPermission();
- Preconditions.checkNotNull(attr, "attr must not be null");
+ Objects.requireNonNull(attr, "attr must not be null");
return AudioSystem.getMinVolumeIndexForAttributes(attr);
}
@@ -2510,7 +2510,7 @@
private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
- Preconditions.checkNotNull(attributes, "attributes must not be null");
+ Objects.requireNonNull(attributes, "attributes must not be null");
int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
return volumeGroupId;
@@ -2521,7 +2521,7 @@
}
private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
- Preconditions.checkNotNull(attributes, "attributes must not be null");
+ Objects.requireNonNull(attributes, "attributes must not be null");
for (final AudioProductStrategy productStrategy :
AudioProductStrategy.getAudioProductStrategies()) {
int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index ff0b015..28f67fe 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -34,6 +34,7 @@
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.Objects;
/**
* A utility to map from an ambient brightness to a display's "backlight" brightness based on the
@@ -702,7 +703,7 @@
"Nits and backlight arrays must not be empty!");
Preconditions.checkArgument(nits.length == backlight.length,
"Nits and backlight arrays must be the same length!");
- Preconditions.checkNotNull(config);
+ Objects.requireNonNull(config);
Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
Preconditions.checkArrayElementsInRange(backlight,
PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
diff --git a/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java b/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
index 1707a62..75d00ff 100644
--- a/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
+++ b/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
@@ -29,6 +29,7 @@
import com.android.server.display.utils.History;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* The DisplayWhiteBalanceController uses the AmbientSensor to detect changes in the ambient
@@ -139,8 +140,8 @@
private static void validateArguments(Handler handler, SensorManager sensorManager, int rate) {
- Preconditions.checkNotNull(handler, "handler cannot be null");
- Preconditions.checkNotNull(sensorManager, "sensorManager cannot be null");
+ Objects.requireNonNull(handler, "handler cannot be null");
+ Objects.requireNonNull(sensorManager, "sensorManager cannot be null");
if (rate <= 0) {
throw new IllegalArgumentException("rate must be positive");
}
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 88a7077..d64fcbc 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -28,6 +28,7 @@
import com.android.server.display.utils.History;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* The DisplayWhiteBalanceController drives display white-balance (automatically correcting the
@@ -475,13 +476,13 @@
AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
AmbientFilter colorTemperatureFilter,
DisplayWhiteBalanceThrottler throttler) {
- Preconditions.checkNotNull(brightnessSensor, "brightnessSensor must not be null");
- Preconditions.checkNotNull(brightnessFilter, "brightnessFilter must not be null");
- Preconditions.checkNotNull(colorTemperatureSensor,
+ Objects.requireNonNull(brightnessSensor, "brightnessSensor must not be null");
+ Objects.requireNonNull(brightnessFilter, "brightnessFilter must not be null");
+ Objects.requireNonNull(colorTemperatureSensor,
"colorTemperatureSensor must not be null");
- Preconditions.checkNotNull(colorTemperatureFilter,
+ Objects.requireNonNull(colorTemperatureFilter,
"colorTemperatureFilter must not be null");
- Preconditions.checkNotNull(throttler, "throttler cannot be null");
+ Objects.requireNonNull(throttler, "throttler cannot be null");
}
private boolean enable() {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
index 6e78894..0efb749 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
@@ -30,6 +30,7 @@
import com.android.server.display.whitebalance.DisplayWhiteBalanceController.Callbacks;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* The DisplayWhiteBalanceSettings holds the state of all the settings related to
@@ -144,8 +145,8 @@
}
private void validateArguments(Context context, Handler handler) {
- Preconditions.checkNotNull(context, "context must not be null");
- Preconditions.checkNotNull(handler, "handler must not be null");
+ Objects.requireNonNull(context, "context must not be null");
+ Objects.requireNonNull(handler, "handler must not be null");
}
private void setEnabled(boolean enabled) {
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
index 080e6ce..a9e8719 100755
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -26,6 +26,7 @@
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Feature action that handles device discovery sequences.
@@ -106,7 +107,7 @@
*/
DeviceDiscoveryAction(HdmiCecLocalDevice source, DeviceDiscoveryCallback callback, int delay) {
super(source);
- mCallback = Preconditions.checkNotNull(callback);
+ mCallback = Objects.requireNonNull(callback);
mDelayPeriod = delay;
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 5865dc4..8b6b614 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1792,10 +1792,18 @@
@GuardedBy("mMethodMap")
private void onCreateInlineSuggestionsRequestLocked(ComponentName componentName,
AutofillId autofillId, IInlineSuggestionsRequestCallback callback) {
- if (mCurMethod != null) {
- executeOrSendMessage(mCurMethod,
- mCaller.obtainMessageOOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
- componentName, autofillId, callback));
+
+ final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+ try {
+ if (imi != null && imi.isInlineSuggestionsEnabled() && mCurMethod != null) {
+ executeOrSendMessage(mCurMethod,
+ mCaller.obtainMessageOOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
+ componentName, autofillId, callback));
+ } else {
+ callback.onInlineSuggestionsUnsupported();
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException calling onCreateInlineSuggestionsRequest(): " + e);
}
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index f3d60f5..b1639a9 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -196,6 +196,15 @@
private void handleIntegrityVerification(Intent intent) {
int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
+
+ // Fail early if we don't have any rules at all.
+ if (!mIntegrityFileManager.initialized()) {
+ Slog.i(TAG, "Rules not initialized. Skipping integrity check.");
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
try {
Slog.i(TAG, "Received integrity verification intent " + intent.toString());
Slog.i(TAG, "Extras " + intent.getExtras());
@@ -376,6 +385,9 @@
String packageName = getPackageNameNormalized(packageAndCert[0]);
String cert = packageAndCert[1];
packageCertMap.put(packageName, cert);
+ } else if (packageAndCert.length == 1
+ && packageAndCert[0].equals(ADB_INSTALLER)) {
+ packageCertMap.put(ADB_INSTALLER, INSTALLER_CERT_NOT_APPLICABLE);
}
}
}
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
index e224724..30cafaa 100644
--- a/services/core/java/com/android/server/integrity/IntegrityFileManager.java
+++ b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
@@ -24,14 +24,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.integrity.model.RuleMetadata;
+import com.android.server.integrity.parser.RuleBinaryParser;
import com.android.server.integrity.parser.RuleMetadataParser;
import com.android.server.integrity.parser.RuleParseException;
import com.android.server.integrity.parser.RuleParser;
-import com.android.server.integrity.parser.RuleXmlParser;
+import com.android.server.integrity.serializer.RuleBinarySerializer;
import com.android.server.integrity.serializer.RuleMetadataSerializer;
import com.android.server.integrity.serializer.RuleSerializeException;
import com.android.server.integrity.serializer.RuleSerializer;
-import com.android.server.integrity.serializer.RuleXmlSerializer;
import java.io.File;
import java.io.FileInputStream;
@@ -57,6 +57,7 @@
private final RuleParser mRuleParser;
private final RuleSerializer mRuleSerializer;
+ private final File mDataDir;
// mRulesDir contains data of the actual rules currently stored.
private final File mRulesDir;
// mStagingDir is used to store the temporary rules / metadata during updating, since we want to
@@ -75,8 +76,8 @@
private IntegrityFileManager() {
this(
- new RuleXmlParser(),
- new RuleXmlSerializer(),
+ new RuleBinaryParser(),
+ new RuleBinarySerializer(),
Environment.getDataSystemDirectory());
}
@@ -84,11 +85,12 @@
IntegrityFileManager(RuleParser ruleParser, RuleSerializer ruleSerializer, File dataDir) {
mRuleParser = ruleParser;
mRuleSerializer = ruleSerializer;
+ mDataDir = dataDir;
mRulesDir = new File(dataDir, "integrity_rules");
mStagingDir = new File(dataDir, "integrity_staging");
- if (!mStagingDir.mkdirs() && mRulesDir.mkdirs()) {
+ if (!mStagingDir.mkdirs() || !mRulesDir.mkdirs()) {
Slog.e(TAG, "Error creating staging and rules directory");
// TODO: maybe throw an exception?
}
@@ -103,6 +105,16 @@
}
}
+ /**
+ * Returns if the rules have been initialized.
+ *
+ * <p>Used to fail early if there are no rules (so we don't need to parse the apk at all).
+ */
+ public boolean initialized() {
+ return new File(mRulesDir, RULES_FILE).exists()
+ && new File(mRulesDir, METADATA_FILE).exists();
+ }
+
/** Write rules to persistent storage. */
public void writeRules(String version, String ruleProvider, List<Rule> rules)
throws IOException, RuleSerializeException {
@@ -146,7 +158,7 @@
private void switchStagingRulesDir() throws IOException {
synchronized (RULES_LOCK) {
- File tmpDir = new File(Environment.getDataSystemDirectory(), "temp");
+ File tmpDir = new File(mDataDir, "temp");
if (!(mRulesDir.renameTo(tmpDir)
&& mStagingDir.renameTo(mRulesDir)
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index 25defb0..22af085 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -36,6 +36,7 @@
import android.content.integrity.Formula;
import android.content.integrity.Rule;
+import com.android.internal.util.Preconditions;
import com.android.server.integrity.IntegrityUtils;
import com.android.server.integrity.model.BitOutputStream;
@@ -46,10 +47,17 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.TreeMap;
/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
public class RuleBinarySerializer implements RuleSerializer {
+ // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format.
+ private static final int INDEXING_BLOCK_SIZE = 100;
+
+ private static final String START_INDEXING_KEY = "START_KEY";
+ private static final String END_INDEXING_KEY = "END_KEY";
+
// Get the byte representation for a list of rules.
@Override
public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
@@ -66,25 +74,34 @@
// Get the byte representation for a list of rules, and write them to an output stream.
@Override
public void serialize(
- List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
+ List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream)
throws RuleSerializeException {
try {
// Determine the indexing groups and the order of the rules within each indexed group.
- Map<Integer, List<Rule>> indexedRules =
+ Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
+ ByteTrackedOutputStream outputStream =
+ new ByteTrackedOutputStream(originalOutputStream);
+
serializeRuleFileMetadata(formatVersion, outputStream);
- serializeIndexedRules(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
- serializeIndexedRules(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
- serializeIndexedRules(indexedRules.get(NOT_INDEXED), outputStream);
+ Map<String, Long> packageNameIndexes =
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
+ Map<String, Long> appCertificateIndexes =
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
+ Map<String, Long> unindexedRulesIndex =
+ serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream);
+
+ // TODO(b/145493956): Write these indexes into a index file provided by integrity file
+ // manager.
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
}
- private void serializeRuleFileMetadata(
- Optional<Integer> formatVersion, OutputStream outputStream) throws IOException {
+ private void serializeRuleFileMetadata(Optional<Integer> formatVersion,
+ ByteTrackedOutputStream outputStream) throws IOException {
int formatVersionValue = formatVersion.orElse(DEFAULT_FORMAT_VERSION);
BitOutputStream bitOutputStream = new BitOutputStream();
@@ -92,17 +109,33 @@
outputStream.write(bitOutputStream.toByteArray());
}
- private void serializeIndexedRules(List<Rule> rules, OutputStream outputStream)
+ private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+ ByteTrackedOutputStream outputStream)
throws IOException {
- if (rules == null) {
- return;
- }
+ Preconditions.checkArgument(rulesMap != null,
+ "serializeRuleList should never be called with null rule list.");
+
BitOutputStream bitOutputStream = new BitOutputStream();
- for (Rule rule : rules) {
- bitOutputStream.clear();
- serializeRule(rule, bitOutputStream);
- outputStream.write(bitOutputStream.toByteArray());
+ Map<String, Long> indexMapping = new TreeMap();
+ long indexTracker = 0;
+
+ indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount());
+ for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+ if (indexTracker >= INDEXING_BLOCK_SIZE) {
+ indexMapping.put(entry.getKey(), outputStream.getWrittenBytesCount());
+ indexTracker = 0;
+ }
+
+ for (Rule rule : entry.getValue()) {
+ bitOutputStream.clear();
+ serializeRule(rule, bitOutputStream);
+ outputStream.write(bitOutputStream.toByteArray());
+ indexTracker++;
+ }
}
+ indexMapping.put(END_INDEXING_KEY, outputStream.getWrittenBytesCount());
+
+ return indexMapping;
}
private void serializeRule(Rule rule, BitOutputStream bitOutputStream) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
index f9c7912..cbc365e 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
@@ -38,23 +38,19 @@
private static final String DEFAULT_RULE_KEY = "N/A";
/**
- * Splits a given rule list into three indexing categories and returns a sorted list of rules
- * per each index.
- *
- * The sorting guarantees an order based on the key but the rules that have the same key
- * can be in arbitrary order. For example, given the rules of [package_name_a_rule_1,
- * package_name_a_rule_2, package_name_b_rule_3, package_name_b_rule_4], the method will
- * guarantee that package_name_b rules (i.e., 3 and 4) will never come before package_name_a
- * rules (i.e., 1 and 2). However, we do not care about the ordering between rule 1 and 2.
- * We also do not care about the ordering between rule 3 and 4.
+ * Splits a given rule list into three indexing categories. Each rule category is returned as a
+ * TreeMap that is sorted by their indexing keys -- where keys correspond to package name for
+ * PACKAGE_NAME_INDEXED rules, app certificate for APP_CERTIFICATE_INDEXED rules and N/A for
+ * NOT_INDEXED rules.
*/
- public static Map<Integer, List<Rule>> splitRulesIntoIndexBuckets(List<Rule> rules) {
+ public static Map<Integer, TreeMap<String, List<Rule>>> splitRulesIntoIndexBuckets(
+ List<Rule> rules) {
if (rules == null) {
throw new IllegalArgumentException(
"Index buckets cannot be created for null rule list.");
}
- Map<Integer, Map<String, List<Rule>>> typeOrganizedRuleMap = new HashMap();
+ Map<Integer, TreeMap<String, List<Rule>>> typeOrganizedRuleMap = new HashMap();
typeOrganizedRuleMap.put(NOT_INDEXED, new TreeMap());
typeOrganizedRuleMap.put(PACKAGE_NAME_INDEXED, new TreeMap());
typeOrganizedRuleMap.put(APP_CERTIFICATE_INDEXED, new TreeMap());
@@ -87,19 +83,7 @@
.add(rule);
}
- // Per indexing type, create the sorted rule set based on their key.
- Map<Integer, List<Rule>> orderedListPerIndexingType = new HashMap<>();
-
- for (Integer indexingKey : typeOrganizedRuleMap.keySet()) {
- List<Rule> sortedRules = new ArrayList();
- for (Map.Entry<String, List<Rule>> entry :
- typeOrganizedRuleMap.get(indexingKey).entrySet()) {
- sortedRules.addAll(entry.getValue());
- }
- orderedListPerIndexingType.put(indexingKey, sortedRules);
- }
-
- return orderedListPerIndexingType;
+ return typeOrganizedRuleMap;
}
private static RuleIndexingDetails getIndexingDetails(Formula formula) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index ebf6a2e..4c04dbc 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -35,6 +35,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.TreeMap;
/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
public class RuleXmlSerializer implements RuleSerializer {
@@ -84,7 +85,7 @@
throws RuleSerializeException {
try {
// Determine the indexing groups and the order of the rules within each indexed group.
- Map<Integer, List<Rule>> indexedRules =
+ Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
// Write the XML formatted rules in order.
@@ -101,10 +102,13 @@
}
}
- private void serializeRuleList(List<Rule> rules, XmlSerializer xmlSerializer)
+ private void serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+ XmlSerializer xmlSerializer)
throws IOException {
- for (Rule rule : rules) {
- serializeRule(rule, xmlSerializer);
+ for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+ for (Rule rule : entry.getValue()) {
+ serializeRule(rule, xmlSerializer);
+ }
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index bcc4c1f..6c65c36 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -151,6 +151,7 @@
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -1594,8 +1595,8 @@
*/
private boolean setLockCredentialInternal(LockscreenCredential credential,
LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
- Preconditions.checkNotNull(credential);
- Preconditions.checkNotNull(savedCredential);
+ Objects.requireNonNull(credential);
+ Objects.requireNonNull(savedCredential);
synchronized (mSpManager) {
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index c53647d..0fe16be 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -57,6 +57,7 @@
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Set;
@@ -228,8 +229,8 @@
* by {@link #setEscrowData} before calling this.
*/
public void recreateFromEscrow(byte[] escrowSplit0) {
- Preconditions.checkNotNull(mEscrowSplit1);
- Preconditions.checkNotNull(mEncryptedEscrowSplit0);
+ Objects.requireNonNull(mEscrowSplit1);
+ Objects.requireNonNull(mEncryptedEscrowSplit0);
recreate(escrowSplit0, mEscrowSplit1);
}
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 1b14ce2..383d5cf 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -75,6 +75,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -302,8 +303,8 @@
checkRecoverKeyStorePermission();
rootCertificateAlias =
mTestCertHelper.getDefaultCertificateAliasIfEmpty(rootCertificateAlias);
- Preconditions.checkNotNull(recoveryServiceCertFile, "recoveryServiceCertFile is null");
- Preconditions.checkNotNull(recoveryServiceSigFile, "recoveryServiceSigFile is null");
+ Objects.requireNonNull(recoveryServiceCertFile, "recoveryServiceCertFile is null");
+ Objects.requireNonNull(recoveryServiceSigFile, "recoveryServiceSigFile is null");
SigXml sigXml;
try {
@@ -393,7 +394,7 @@
*/
public void setRecoveryStatus(@NonNull String alias, int status) throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(alias, "alias is null");
+ Objects.requireNonNull(alias, "alias is null");
long updatedRows = mDatabase.setRecoveryStatus(Binder.getCallingUid(), alias, status);
if (updatedRows < 0) {
throw new ServiceSpecificException(
@@ -424,7 +425,7 @@
@NonNull @KeyChainProtectionParams.UserSecretType int[] secretTypes)
throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(secretTypes, "secretTypes is null");
+ Objects.requireNonNull(secretTypes, "secretTypes is null");
int userId = UserHandle.getCallingUserId();
int uid = Binder.getCallingUid();
@@ -556,11 +557,11 @@
checkRecoverKeyStorePermission();
rootCertificateAlias =
mTestCertHelper.getDefaultCertificateAliasIfEmpty(rootCertificateAlias);
- Preconditions.checkNotNull(sessionId, "invalid session");
- Preconditions.checkNotNull(verifierCertPath, "verifierCertPath is null");
- Preconditions.checkNotNull(vaultParams, "vaultParams is null");
- Preconditions.checkNotNull(vaultChallenge, "vaultChallenge is null");
- Preconditions.checkNotNull(secrets, "secrets is null");
+ Objects.requireNonNull(sessionId, "invalid session");
+ Objects.requireNonNull(verifierCertPath, "verifierCertPath is null");
+ Objects.requireNonNull(vaultParams, "vaultParams is null");
+ Objects.requireNonNull(vaultChallenge, "vaultChallenge is null");
+ Objects.requireNonNull(secrets, "secrets is null");
CertPath certPath;
try {
certPath = verifierCertPath.getCertPath();
@@ -666,13 +667,13 @@
*/
public void closeSession(@NonNull String sessionId) throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(sessionId, "invalid session");
+ Objects.requireNonNull(sessionId, "invalid session");
mRecoverySessionStorage.remove(Binder.getCallingUid(), sessionId);
}
public void removeKey(@NonNull String alias) throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(alias, "alias is null");
+ Objects.requireNonNull(alias, "alias is null");
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
@@ -711,7 +712,7 @@
public String generateKeyWithMetadata(@NonNull String alias, @Nullable byte[] metadata)
throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(alias, "alias is null");
+ Objects.requireNonNull(alias, "alias is null");
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
@@ -771,8 +772,8 @@
public @Nullable String importKeyWithMetadata(@NonNull String alias, @NonNull byte[] keyBytes,
@Nullable byte[] metadata) throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(alias, "alias is null");
- Preconditions.checkNotNull(keyBytes, "keyBytes is null");
+ Objects.requireNonNull(alias, "alias is null");
+ Objects.requireNonNull(keyBytes, "keyBytes is null");
if (keyBytes.length != RecoverableKeyGenerator.KEY_SIZE_BITS / Byte.SIZE) {
Log.e(TAG, "The given key for import doesn't have the required length "
+ RecoverableKeyGenerator.KEY_SIZE_BITS);
@@ -816,7 +817,7 @@
*/
public @Nullable String getKey(@NonNull String alias) throws RemoteException {
checkRecoverKeyStorePermission();
- Preconditions.checkNotNull(alias, "alias is null");
+ Objects.requireNonNull(alias, "alias is null");
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
return getAlias(userId, uid, alias);
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 423001f..f8d8f9f 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -286,6 +286,11 @@
if (mActiveConnection != connection) {
return;
}
+ if (sessionInfo != null) {
+ sessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+ }
mCallback.onSessionCreated(this, sessionInfo, requestId);
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 0bdcc97..82d2250 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1071,12 +1071,6 @@
return;
}
- //TODO: remove this when we are sure that request id is properly implemented.
- if (matchingRequest.mClientRecord.mClientId != toClientId(requestId)) {
- Slog.w(TAG, "Client id is changed. This shouldn't happen.");
- return;
- }
-
mSessionCreationRequests.remove(matchingRequest);
if (sessionInfo == null) {
@@ -1086,21 +1080,17 @@
return;
}
- RouteSessionInfo sessionInfoWithProviderId = new RouteSessionInfo.Builder(sessionInfo)
- .setProviderId(provider.getUniqueId())
- .build();
-
String originalRouteId = matchingRequest.mRoute.getId();
String originalCategory = matchingRequest.mControlCategory;
Client2Record client2Record = matchingRequest.mClientRecord;
- if (!sessionInfoWithProviderId.getSelectedRoutes().contains(originalRouteId)
+ if (!sessionInfo.getSelectedRoutes().contains(originalRouteId)
|| !TextUtils.equals(originalCategory,
- sessionInfoWithProviderId.getControlCategory())) {
+ sessionInfo.getControlCategory())) {
Slog.w(TAG, "Created session doesn't match the original request."
+ " originalRouteId=" + originalRouteId
+ ", originalCategory=" + originalCategory + ", requestId=" + requestId
- + ", sessionInfo=" + sessionInfoWithProviderId);
+ + ", sessionInfo=" + sessionInfo);
notifySessionCreationFailed(matchingRequest.mClientRecord,
toClientRequestId(requestId));
return;
@@ -1108,8 +1098,8 @@
// Succeeded
notifySessionCreated(matchingRequest.mClientRecord,
- sessionInfoWithProviderId, toClientRequestId(requestId));
- mSessionToClientMap.put(sessionInfoWithProviderId.getUniqueSessionId(), client2Record);
+ sessionInfo, toClientRequestId(requestId));
+ mSessionToClientMap.put(sessionInfo.getUniqueSessionId(), client2Record);
// TODO: Tell managers for the session creation
}
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 4cb41da..ef8f647 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -45,12 +45,12 @@
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.Preconditions;
import com.android.server.ConnectivityService;
import com.android.server.EventLogTags;
import com.android.server.connectivity.Vpn;
import java.util.List;
+import java.util.Objects;
/**
* State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be
@@ -90,11 +90,11 @@
@NonNull Handler handler,
@NonNull Vpn vpn,
@NonNull VpnProfile profile) {
- mContext = Preconditions.checkNotNull(context);
- mConnService = Preconditions.checkNotNull(connService);
- mHandler = Preconditions.checkNotNull(handler);
- mVpn = Preconditions.checkNotNull(vpn);
- mProfile = Preconditions.checkNotNull(profile);
+ mContext = Objects.requireNonNull(context);
+ mConnService = Objects.requireNonNull(connService);
+ mHandler = Objects.requireNonNull(handler);
+ mVpn = Objects.requireNonNull(vpn);
+ mProfile = Objects.requireNonNull(profile);
final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 99562eb..2390da5e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -91,7 +91,6 @@
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.internal.util.ArrayUtils.appendInt;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -614,12 +613,12 @@
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
INetworkManagementService networkManagement, IPackageManager pm, Clock clock,
File systemDir, boolean suppressDefaultPolicy) {
- mContext = checkNotNull(context, "missing context");
- mActivityManager = checkNotNull(activityManager, "missing activityManager");
- mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
+ mContext = Objects.requireNonNull(context, "missing context");
+ mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager");
+ mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement");
mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
Context.DEVICE_IDLE_CONTROLLER));
- mClock = checkNotNull(clock, "missing Clock");
+ mClock = Objects.requireNonNull(clock, "missing Clock");
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
mIPm = pm;
@@ -646,7 +645,7 @@
}
public void bindConnectivityManager(IConnectivityManager connManager) {
- mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
+ mConnManager = Objects.requireNonNull(connManager, "missing IConnectivityManager");
}
@GuardedBy("mUidRulesFirstLock")
@@ -3106,17 +3105,16 @@
return;
}
- long applicableNetworkTypes = 0;
+ final ArraySet<Integer> applicableNetworkTypes = new ArraySet<Integer>();
boolean allNetworks = false;
for (SubscriptionPlan plan : plans) {
if (plan.getNetworkTypes() == null) {
allNetworks = true;
} else {
- if ((applicableNetworkTypes & plan.getNetworkTypesBitMask()) != 0) {
+ final int[] networkTypes = plan.getNetworkTypes();
+ if (!addAll(applicableNetworkTypes, networkTypes)) {
throw new IllegalArgumentException(
"Multiple subscription plans defined for a single network type.");
- } else {
- applicableNetworkTypes |= plan.getNetworkTypesBitMask();
}
}
}
@@ -3128,6 +3126,19 @@
}
}
+ /**
+ * Adds all of the {@code elements} to the {@code set}.
+ *
+ * @return {@code false} if any element is not added because the set already have the value.
+ */
+ private static boolean addAll(@NonNull Set<Integer> set, @NonNull int... elements) {
+ boolean result = true;
+ for (int element : elements) {
+ result &= set.add(element);
+ }
+ return result;
+ }
+
@Override
public SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage) {
enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
@@ -3295,7 +3306,7 @@
enforceSubscriptionPlanValidity(plans);
for (SubscriptionPlan plan : plans) {
- Preconditions.checkNotNull(plan);
+ Objects.requireNonNull(plan);
}
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 6af962b..9eff5d1 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -21,8 +21,6 @@
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
import android.net.NetworkStatsHistory;
@@ -54,6 +52,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
/**
* Logic to record deltas between periodic {@link NetworkStats} snapshots into
@@ -116,9 +115,9 @@
*/
public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
- mRotator = checkNotNull(rotator, "missing FileRotator");
- mObserver = checkNotNull(observer, "missing NonMonotonicObserver");
- mDropBox = checkNotNull(dropBox, "missing DropBoxManager");
+ mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
+ mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
+ mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
mCookie = cookie;
mBucketDuration = bucketDuration;
@@ -165,7 +164,7 @@
* as reference is valid.
*/
public NetworkStatsCollection getOrLoadCompleteLocked() {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
if (res == null) {
res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
@@ -175,7 +174,7 @@
}
public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
if (res == null) {
res = loadLocked(start, end);
@@ -280,7 +279,7 @@
* {@link #mPersistThresholdBytes}.
*/
public void maybePersistLocked(long currentTimeMillis) {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
final long pendingBytes = mPending.getTotalBytes();
if (pendingBytes >= mPersistThresholdBytes) {
forcePersistLocked(currentTimeMillis);
@@ -293,7 +292,7 @@
* Force persisting any pending deltas.
*/
public void forcePersistLocked(long currentTimeMillis) {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
if (mPending.isDirty()) {
if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
try {
@@ -356,7 +355,7 @@
private final NetworkStatsCollection mCollection;
public CombiningRewriter(NetworkStatsCollection collection) {
- mCollection = checkNotNull(collection, "missing NetworkStatsCollection");
+ mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
}
@Override
@@ -418,7 +417,7 @@
}
public void importLegacyNetworkLocked(File file) throws IOException {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
// legacy file still exists; start empty to avoid double importing
mRotator.deleteAll();
@@ -438,7 +437,7 @@
}
public void importLegacyUidLocked(File file) throws IOException {
- checkNotNull(mRotator, "missing FileRotator");
+ Objects.requireNonNull(mRotator, "missing FileRotator");
// legacy file still exists; start empty to avoid double importing
mRotator.deleteAll();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0288f0c..ec8a8e7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -65,7 +65,6 @@
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -148,6 +147,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
/**
* Collect and persist detailed network statistics, and provide this data to
@@ -357,17 +357,18 @@
TelephonyManager teleManager, NetworkStatsSettings settings,
NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
File baseDir) {
- mContext = checkNotNull(context, "missing Context");
- mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
- mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
- mClock = checkNotNull(clock, "missing Clock");
- mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
- mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
- mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
- mStatsFactory = checkNotNull(factory, "missing factory");
- mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
- mSystemDir = checkNotNull(systemDir, "missing systemDir");
- mBaseDir = checkNotNull(baseDir, "missing baseDir");
+ mContext = Objects.requireNonNull(context, "missing Context");
+ mNetworkManager = Objects.requireNonNull(networkManager,
+ "missing INetworkManagementService");
+ mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
+ mClock = Objects.requireNonNull(clock, "missing Clock");
+ mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
+ mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager");
+ mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
+ mStatsFactory = Objects.requireNonNull(factory, "missing factory");
+ mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
+ mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
+ mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
}
@@ -896,11 +897,11 @@
@Override
public DataUsageRequest registerUsageCallback(String callingPackage,
DataUsageRequest request, Messenger messenger, IBinder binder) {
- checkNotNull(callingPackage, "calling package is null");
- checkNotNull(request, "DataUsageRequest is null");
- checkNotNull(request.template, "NetworkTemplate is null");
- checkNotNull(messenger, "messenger is null");
- checkNotNull(binder, "binder is null");
+ Objects.requireNonNull(callingPackage, "calling package is null");
+ Objects.requireNonNull(request, "DataUsageRequest is null");
+ Objects.requireNonNull(request.template, "NetworkTemplate is null");
+ Objects.requireNonNull(messenger, "messenger is null");
+ Objects.requireNonNull(binder, "binder is null");
int callingUid = Binder.getCallingUid();
@NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
@@ -921,7 +922,7 @@
@Override
public void unregisterUsageRequest(DataUsageRequest request) {
- checkNotNull(request, "DataUsageRequest is null");
+ Objects.requireNonNull(request, "DataUsageRequest is null");
int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -1795,7 +1796,7 @@
private final ContentResolver mResolver;
public DefaultNetworkStatsSettings(Context context) {
- mResolver = checkNotNull(context.getContentResolver());
+ mResolver = Objects.requireNonNull(context.getContentResolver());
// TODO: adjust these timings for production builds
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 12afef2..f42f4f7 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2261,8 +2261,8 @@
private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromApp, boolean fromListener) {
- Preconditions.checkNotNull(group);
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(group);
+ Objects.requireNonNull(pkg);
final NotificationChannelGroup preUpdate =
mPreferencesHelper.getNotificationChannelGroup(group.getId(), pkg, uid);
@@ -3005,7 +3005,7 @@
boolean needsPolicyFileChange = false;
for (int i = 0; i < channelsSize; i++) {
final NotificationChannel channel = channels.get(i);
- Preconditions.checkNotNull(channel, "channel in list is null");
+ Objects.requireNonNull(channel, "channel in list is null");
needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid,
channel, true /* fromTargetApp */,
mConditionProviders.isPackageOrComponentAllowed(
@@ -3126,7 +3126,7 @@
public void updateNotificationChannelForPackage(String pkg, int uid,
NotificationChannel channel) {
enforceSystemOrSystemUI("Caller not system or systemui");
- Preconditions.checkNotNull(channel);
+ Objects.requireNonNull(channel);
updateNotificationChannelInt(pkg, uid, channel, false);
}
@@ -3877,21 +3877,21 @@
@Override
public AutomaticZenRule getAutomaticZenRule(String id) throws RemoteException {
- Preconditions.checkNotNull(id, "Id is null");
+ Objects.requireNonNull(id, "Id is null");
enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRule");
return mZenModeHelper.getAutomaticZenRule(id);
}
@Override
public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
- Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
- Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+ Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+ Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
&& automaticZenRule.getConfigurationActivity() == null) {
throw new NullPointerException(
"Rule must have a conditionproviderservice and/or configuration activity");
}
- Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
if (automaticZenRule.getZenPolicy() != null
&& automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -3906,14 +3906,14 @@
@Override
public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
throws RemoteException {
- Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
- Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+ Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+ Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
&& automaticZenRule.getConfigurationActivity() == null) {
throw new NullPointerException(
"Rule must have a conditionproviderservice and/or configuration activity");
}
- Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
@@ -3922,7 +3922,7 @@
@Override
public boolean removeAutomaticZenRule(String id) throws RemoteException {
- Preconditions.checkNotNull(id, "Id is null");
+ Objects.requireNonNull(id, "Id is null");
// Verify that they can modify zen rules.
enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
@@ -3931,7 +3931,7 @@
@Override
public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
- Preconditions.checkNotNull(packageName, "Package name is null");
+ Objects.requireNonNull(packageName, "Package name is null");
enforceSystemOrSystemUI("removeAutomaticZenRules");
return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
@@ -3939,7 +3939,7 @@
@Override
public int getRuleInstanceCount(ComponentName owner) throws RemoteException {
- Preconditions.checkNotNull(owner, "Owner is null");
+ Objects.requireNonNull(owner, "Owner is null");
enforceSystemOrSystemUI("getRuleInstanceCount");
return mZenModeHelper.getCurrentInstanceCount(owner);
@@ -3947,8 +3947,8 @@
@Override
public void setAutomaticZenRuleState(String id, Condition condition) {
- Preconditions.checkNotNull(id, "id is null");
- Preconditions.checkNotNull(condition, "Condition is null");
+ Objects.requireNonNull(id, "id is null");
+ Objects.requireNonNull(condition, "Condition is null");
enforcePolicyAccess(Binder.getCallingUid(), "setAutomaticZenRuleState");
@@ -4292,7 +4292,7 @@
@Override
public boolean isNotificationListenerAccessGranted(ComponentName listener) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystemOrSameApp(listener.getPackageName());
return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
getCallingUserHandle().getIdentifier());
@@ -4301,7 +4301,7 @@
@Override
public boolean isNotificationListenerAccessGrantedForUser(ComponentName listener,
int userId) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystem();
return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
userId);
@@ -4309,7 +4309,7 @@
@Override
public boolean isNotificationAssistantAccessGranted(ComponentName assistant) {
- Preconditions.checkNotNull(assistant);
+ Objects.requireNonNull(assistant);
checkCallerIsSystemOrSameApp(assistant.getPackageName());
return mAssistants.isPackageOrComponentAllowed(assistant.flattenToString(),
getCallingUserHandle().getIdentifier());
@@ -4332,7 +4332,7 @@
@Override
public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
boolean granted) {
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(listener);
checkCallerIsSystemOrShell();
final long identity = Binder.clearCallingIdentity();
try {
@@ -4450,7 +4450,7 @@
public void updateNotificationChannelGroupFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user,
NotificationChannelGroup group) throws RemoteException {
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, false);
createNotificationChannelGroup(
pkg, getUidForPackageAndUser(pkg, user), group, false, true);
@@ -4460,9 +4460,9 @@
@Override
public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
String pkg, UserHandle user, NotificationChannel channel) throws RemoteException {
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(channel);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, false);
updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
@@ -4471,8 +4471,8 @@
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, true);
return mPreferencesHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
@@ -4483,8 +4483,8 @@
public ParceledListSlice<NotificationChannelGroup>
getNotificationChannelGroupsFromPrivilegedListener(
INotificationListener token, String pkg, UserHandle user) throws RemoteException {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(user);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, true);
List<NotificationChannelGroup> groups = new ArrayList<>();
@@ -4520,7 +4520,7 @@
@Override
public boolean isPackagePaused(String pkg) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
checkCallerIsSameApp(pkg);
return isPackagePausedOrSuspended(pkg, Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index b1ffa8c..cdb0a17 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -621,10 +621,10 @@
@Override
public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromTargetApp) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(group);
- Preconditions.checkNotNull(group.getId());
- Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(group);
+ Objects.requireNonNull(group.getId());
+ Objects.requireNonNull(!TextUtils.isEmpty(group.getName()));
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -658,9 +658,9 @@
@Override
public boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel,
boolean fromTargetApp, boolean hasDndAccess) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(channel.getId());
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(channel);
+ Objects.requireNonNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
boolean needsPolicyFileChange = false;
synchronized (mPackagePreferences) {
@@ -788,8 +788,8 @@
@Override
public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
boolean fromUser) {
- Preconditions.checkNotNull(updatedChannel);
- Preconditions.checkNotNull(updatedChannel.getId());
+ Objects.requireNonNull(updatedChannel);
+ Objects.requireNonNull(updatedChannel.getId());
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -850,7 +850,7 @@
@Override
public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -891,8 +891,8 @@
@Override
@VisibleForTesting
public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
- Preconditions.checkNotNull(pkg);
- Preconditions.checkNotNull(channelId);
+ Objects.requireNonNull(pkg);
+ Objects.requireNonNull(channelId);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -904,7 +904,7 @@
@Override
public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -993,7 +993,7 @@
public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
int uid, String groupId, boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
@@ -1016,7 +1016,7 @@
public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -1029,7 +1029,7 @@
@Override
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1111,7 +1111,7 @@
@Override
public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
boolean includeDeleted) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
List<NotificationChannel> channels = new ArrayList<>();
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1168,7 +1168,7 @@
}
public int getDeletedChannelCount(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
int deletedCount = 0;
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1187,7 +1187,7 @@
}
public int getBlockedChannelCount(String pkg, int uid) {
- Preconditions.checkNotNull(pkg);
+ Objects.requireNonNull(pkg);
int blockedCount = 0;
synchronized (mPackagePreferences) {
PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 9a1b30d..1e2d52d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -38,6 +38,7 @@
import com.android.server.SystemConfig;
import java.io.FileDescriptor;
+import java.util.Objects;
/**
* Implementation of the service that provides a privileged API to capture and consume bugreports.
@@ -67,9 +68,9 @@
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
- Preconditions.checkNotNull(callingPackage);
- Preconditions.checkNotNull(bugreportFd);
- Preconditions.checkNotNull(listener);
+ Objects.requireNonNull(callingPackage);
+ Objects.requireNonNull(bugreportFd);
+ Objects.requireNonNull(listener);
validateBugreportMode(bugreportMode);
final long identity = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 785ca7d..04e7372 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11319,6 +11319,12 @@
"Static shared libs cannot declare permission groups");
}
+ // Static shared libs cannot declare features
+ if (pkg.getFeatures() != null && !pkg.getFeatures().isEmpty()) {
+ throw new PackageManagerException(
+ "Static shared libs cannot declare features");
+ }
+
// Static shared libs cannot declare permissions
if (pkg.getPermissions() != null && !pkg.getPermissions().isEmpty()) {
throw new PackageManagerException(
@@ -12872,7 +12878,7 @@
@Override
public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
- Preconditions.checkNotNull("packageNames cannot be null", packageNames);
+ Preconditions.checkNotNull(packageNames, "packageNames cannot be null");
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
"getUnsuspendablePackagesForUser");
final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 605f869..9cd6f16 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3025,10 +3025,9 @@
@Override
public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) {
- mContext.enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
- "Must be able to revoke runtime permissions to register permissions as one time.");
- mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
- "Must be able to access usage stats to register permissions as one time.");
+ mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
+ "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
+ + " to register permissions as one time.");
packageName = Preconditions.checkNotNull(packageName);
long token = Binder.clearCallingIdentity();
@@ -3042,10 +3041,9 @@
@Override
public void stopOneTimePermissionSession(String packageName, @UserIdInt int userId) {
- mContext.enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
- "Must be able to revoke runtime permissions to remove permissions as one time.");
- mContext.enforceCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS,
- "Must be able to access usage stats to remove permissions as one time.");
+ mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
+ "Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
+ + " to remove permissions as one time.");
Preconditions.checkNotNull(packageName);
long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index f0e4625..4142e6f 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -49,6 +49,7 @@
import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState;
import java.util.ArrayList;
+import java.util.Objects;
/**
* Responsible for battery saver mode transition logic.
@@ -237,7 +238,7 @@
private PowerManager getPowerManager() {
if (mPowerManager == null) {
mPowerManager =
- Preconditions.checkNotNull(mContext.getSystemService(PowerManager.class));
+ Objects.requireNonNull(mContext.getSystemService(PowerManager.class));
}
return mPowerManager;
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c4522e0..392792d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -511,7 +511,7 @@
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
callback);
@@ -531,7 +531,7 @@
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
callback);
@@ -550,7 +550,7 @@
"clearRoleHoldersAsUser");
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkNotNull(callback, "callback cannot be null");
+ Objects.requireNonNull(callback, "callback cannot be null");
getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
}
@@ -566,7 +566,7 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"addOnRoleHoldersChangedListenerAsUser");
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
userId);
@@ -584,7 +584,7 @@
getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
"removeOnRoleHoldersChangedListenerAsUser");
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
if (listener == null) {
@@ -599,7 +599,7 @@
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
"setRoleNamesFromController");
- Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
+ Objects.requireNonNull(roleNames, "roleNames cannot be null");
int userId = UserHandle.getCallingUserId();
getOrCreateUserState(userId).setRoleNames(roleNames);
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index 1123f70..e6e6e23 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import android.content.pm.PackageManager;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.os.storage.StorageManager;
@@ -119,11 +120,22 @@
}
try {
- mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo,
- userId, rollbackId, storageFlags);
+ switch (packageRollbackInfo.getRollbackDataPolicy()) {
+ case PackageManager.RollbackDataPolicy.WIPE:
+ mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(),
+ userId, storageFlags, 0);
+ break;
+ case PackageManager.RollbackDataPolicy.RESTORE:
+ mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId,
+ seInfo, userId, rollbackId, storageFlags);
+ break;
+ default:
+ break;
+ }
} catch (InstallerException ie) {
- Slog.e(TAG, "Unable to restore app data snapshot: "
- + packageRollbackInfo.getPackageName(), ie);
+ Slog.e(TAG, "Unable to restore/wipe app data: "
+ + packageRollbackInfo.getPackageName() + " policy="
+ + packageRollbackInfo.getRollbackDataPolicy(), ie);
}
return changedRollback;
@@ -207,13 +219,24 @@
if (hasPendingRestore) {
try {
- mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
- ri.seInfo, userId, rollback.info.getRollbackId(),
- Installer.FLAG_STORAGE_CE);
+ switch (info.getRollbackDataPolicy()) {
+ case PackageManager.RollbackDataPolicy.WIPE:
+ mInstaller.clearAppData(null, info.getPackageName(), userId,
+ Installer.FLAG_STORAGE_CE, 0);
+ break;
+ case PackageManager.RollbackDataPolicy.RESTORE:
+ mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
+ ri.seInfo, userId, rollback.info.getRollbackId(),
+ Installer.FLAG_STORAGE_CE);
+ break;
+ default:
+ break;
+ }
info.removeRestoreInfo(ri);
} catch (InstallerException ie) {
- Slog.e(TAG, "Unable to restore app data snapshot for: "
- + info.getPackageName(), ie);
+ Slog.e(TAG, "Unable to restore/wipe app data for: "
+ + info.getPackageName() + " policy="
+ + info.getRollbackDataPolicy(), ie);
}
}
}
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 6898e1c..88c1564 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -306,7 +306,7 @@
* @return boolean True if the rollback was enabled successfully for the specified package.
*/
boolean enableForPackage(String packageName, long newVersion, long installedVersion,
- boolean isApex, String sourceDir, String[] splitSourceDirs) {
+ boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) {
try {
RollbackStore.backupPackageCodePath(this, packageName, sourceDir);
if (!ArrayUtils.isEmpty(splitSourceDirs)) {
@@ -323,7 +323,8 @@
new VersionedPackage(packageName, newVersion),
new VersionedPackage(packageName, installedVersion),
new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
- isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */);
+ isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */,
+ rollbackDataPolicy);
synchronized (mLock) {
info.getPackages().add(packageRollbackInfo);
@@ -344,10 +345,12 @@
for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
if (pkgRollbackInfo.getPackageName().equals(packageName)) {
- dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
-
- RollbackStore.saveRollback(this);
- pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+ if (pkgRollbackInfo.getRollbackDataPolicy()
+ == PackageManager.RollbackDataPolicy.RESTORE) {
+ dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
+ pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+ RollbackStore.saveRollback(this);
+ }
break;
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 6cdfcff..1475ab9 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -780,6 +780,33 @@
return enableRollbackForPackageSession(newRollback.rollback, packageSession);
}
+ private void removeRollbackForPackageSessionId(int sessionId) {
+ if (LOCAL_LOGV) {
+ Slog.v(TAG, "removeRollbackForPackageSessionId=" + sessionId);
+ }
+
+ synchronized (mLock) {
+ NewRollback newRollback = getNewRollbackForPackageSessionLocked(sessionId);
+ if (newRollback != null) {
+ Slog.w(TAG, "Delete new rollback id=" + newRollback.rollback.info.getRollbackId()
+ + " for session id=" + sessionId);
+ mNewRollbacks.remove(newRollback);
+ newRollback.rollback.delete(mAppDataRollbackHelper);
+ }
+ Iterator<Rollback> iter = mRollbacks.iterator();
+ while (iter.hasNext()) {
+ Rollback rollback = iter.next();
+ if (rollback.getStagedSessionId() == sessionId) {
+ Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId()
+ + " for session id=" + sessionId);
+ iter.remove();
+ rollback.delete(mAppDataRollbackHelper);
+ break;
+ }
+ }
+ }
+ }
+
/**
* Do code and userdata backups to enable rollback of the given session.
* In case of multiPackage sessions, <code>session</code> should be one of
@@ -841,7 +868,7 @@
ApplicationInfo appInfo = pkgInfo.applicationInfo;
return rollback.enableForPackage(packageName, newPackage.versionCode,
pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir,
- appInfo.splitSourceDirs);
+ appInfo.splitSourceDirs, session.rollbackDataPolicy);
}
@Override
@@ -944,7 +971,7 @@
}
}
- Rollback rollback = completeEnableRollback(newRollback, true);
+ Rollback rollback = completeEnableRollback(newRollback);
if (rollback == null) {
result.offer(-1);
} else {
@@ -1089,19 +1116,28 @@
if (LOCAL_LOGV) {
Slog.v(TAG, "SessionCallback.onFinished id=" + sessionId + " success=" + success);
}
- NewRollback newRollback;
- synchronized (mLock) {
- newRollback = getNewRollbackForPackageSessionLocked(sessionId);
- if (newRollback != null) {
- mNewRollbacks.remove(newRollback);
- }
- }
- if (newRollback != null) {
- Rollback rollback = completeEnableRollback(newRollback, success);
- if (rollback != null && !rollback.isStaged()) {
- makeRollbackAvailable(rollback);
+ if (success) {
+ NewRollback newRollback;
+ synchronized (mLock) {
+ newRollback = getNewRollbackForPackageSessionLocked(sessionId);
+ if (newRollback != null && newRollback.notifySessionWithSuccess()) {
+ mNewRollbacks.remove(newRollback);
+ } else {
+ // Not all child sessions finished with success.
+ // Don't enable the rollback yet.
+ newRollback = null;
+ }
}
+
+ if (newRollback != null) {
+ Rollback rollback = completeEnableRollback(newRollback);
+ if (rollback != null && !rollback.isStaged()) {
+ makeRollbackAvailable(rollback);
+ }
+ }
+ } else {
+ removeRollbackForPackageSessionId(sessionId);
}
// Clear the queue so it will never be leaked to next tests.
@@ -1116,16 +1152,10 @@
* @return the Rollback instance for a successfully enable-completed rollback,
* or null on error.
*/
- private Rollback completeEnableRollback(NewRollback newRollback, boolean success) {
+ private Rollback completeEnableRollback(NewRollback newRollback) {
Rollback rollback = newRollback.rollback;
if (LOCAL_LOGV) {
- Slog.v(TAG, "completeEnableRollback id="
- + rollback.info.getRollbackId() + " success=" + success);
- }
- if (!success) {
- // The install session was aborted, clean up the pending install.
- rollback.delete(mAppDataRollbackHelper);
- return null;
+ Slog.v(TAG, "completeEnableRollback id=" + rollback.info.getRollbackId());
}
if (newRollback.isCancelled()) {
@@ -1251,6 +1281,14 @@
@GuardedBy("mNewRollbackLock")
private boolean mIsCancelled = false;
+ /**
+ * The number of sessions in the install which are notified with success by
+ * {@link PackageInstaller.SessionCallback#onFinished(int, boolean)}.
+ * This NewRollback will be enabled only after all child sessions finished with success.
+ */
+ @GuardedBy("mNewRollbackLock")
+ private int mNumPackageSessionsWithSuccess;
+
private final Object mNewRollbackLock = new Object();
NewRollback(Rollback rollback, int[] packageSessionIds) {
@@ -1322,6 +1360,17 @@
int getPackageSessionIdCount() {
return mPackageSessionIds.length;
}
+
+ /**
+ * Called when a child session finished with success.
+ * Returns true when all child sessions are notified with success. This NewRollback will be
+ * enabled only after all child sessions finished with success.
+ */
+ boolean notifySessionWithSuccess() {
+ synchronized (mNewRollbackLock) {
+ return ++mNumPackageSessionsWithSuccess == mPackageSessionIds.length;
+ }
+ }
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index bb09584..162a695 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -120,9 +120,7 @@
RollbackInfo rollback = getAvailableRollback(failedPackage);
if (rollback == null) {
- Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
- + failedPackage.getPackageName() + "] with versionCode: ["
- + failedPackage.getVersionCode() + "]");
+ Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage);
return false;
}
rollbackPackage(rollback, failedPackage, rollbackReason);
@@ -212,11 +210,7 @@
RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
- boolean hasFailedPackage = packageRollback.getPackageName().equals(
- failedPackage.getPackageName())
- && packageRollback.getVersionRolledBackFrom().getVersionCode()
- == failedPackage.getVersionCode();
- if (hasFailedPackage) {
+ if (packageRollback.getVersionRolledBackFrom().equals(failedPackage)) {
return rollback;
}
}
@@ -361,15 +355,6 @@
}
}
- private VersionedPackage getVersionedPackage(String packageName) {
- try {
- return new VersionedPackage(packageName, mContext.getPackageManager().getPackageInfo(
- packageName, 0 /* flags */).getLongVersionCode());
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
- }
-
/**
* Rolls back the session that owns {@code failedPackage}
*
@@ -432,14 +417,8 @@
List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks();
for (RollbackInfo rollback : rollbacks) {
- String samplePackageName = rollback.getPackages().get(0).getPackageName();
- VersionedPackage sampleVersionedPackage = getVersionedPackage(samplePackageName);
- if (sampleVersionedPackage == null) {
- Slog.e(TAG, "Failed to rollback " + samplePackageName);
- continue;
- }
- rollbackPackage(rollback, sampleVersionedPackage,
- PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
+ rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 550c754..df75a29 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -21,6 +21,7 @@
import static com.android.server.rollback.Rollback.rollbackStateFromString;
import android.annotation.NonNull;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
@@ -345,6 +346,8 @@
json.put("installedUsers", convertToJsonArray(snapshottedUsers));
json.put("ceSnapshotInodes", ceSnapshotInodesToJson(info.getCeSnapshotInodes()));
+ json.put("rollbackDataPolicy", info.getRollbackDataPolicy());
+
return json;
}
@@ -367,8 +370,13 @@
final SparseLongArray ceSnapshotInodes = ceSnapshotInodesFromJson(
json.getJSONArray("ceSnapshotInodes"));
+ // Backward compatibility: no such field for old versions.
+ final int rollbackDataPolicy = json.optInt("rollbackDataPolicy",
+ PackageManager.RollbackDataPolicy.RESTORE);
+
return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
- pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes);
+ pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes,
+ rollbackDataPolicy);
}
private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 0bbb179..e90c02a 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -59,7 +59,7 @@
}
@Override
- public boolean isAppSourceCertificateTrusted(byte[] certificateBytes) {
+ public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes) {
enforceAnyCallingPermissions(
android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
android.Manifest.permission.INSTALL_PACKAGES);
@@ -67,7 +67,10 @@
if (!isApkVeritySupported()) {
return false;
}
-
+ if (certificateBytes == null) {
+ Slog.w(TAG, "Received a null certificate");
+ return false;
+ }
return mTrustedCertificates.contains(toCertificate(certificateBytes));
} catch (CertificateException e) {
Slog.e(TAG, "Failed to convert the certificate: " + e);
@@ -122,7 +125,12 @@
}
for (File cert : files) {
- collectCertificate(Files.readAllBytes(cert.toPath()));
+ byte[] certificateBytes = Files.readAllBytes(cert.toPath());
+ if (certificateBytes == null) {
+ Slog.w(TAG, "The certificate file is empty, ignoring " + cert);
+ continue;
+ }
+ collectCertificate(certificateBytes);
}
} catch (IOException e) {
Slog.wtf(TAG, "Failed to load fs-verity certificate from " + path, e);
@@ -146,10 +154,10 @@
* Tries to convert {@code bytes} into an X.509 certificate and store in memory.
* Errors need to be surpressed in order fo the next certificates to still be collected.
*/
- private void collectCertificate(@Nullable byte[] bytes) {
+ private void collectCertificate(@NonNull byte[] bytes) {
try {
mTrustedCertificates.add(toCertificate(bytes));
- } catch (CertificateException | AssertionError e) {
+ } catch (CertificateException e) {
Slog.e(TAG, "Invalid certificate, ignored: " + e);
}
}
@@ -159,7 +167,7 @@
* the rest. The rational is to make it harder to smuggle.
*/
@NonNull
- private static X509Certificate toCertificate(@Nullable byte[] bytes)
+ private static X509Certificate toCertificate(@NonNull byte[] bytes)
throws CertificateException {
Certificate certificate = sCertFactory.generateCertificate(new ByteArrayInputStream(bytes));
if (!(certificate instanceof X509Certificate)) {
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 3b2f324..7c8c494 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -106,7 +106,7 @@
@VisibleForTesting
SliceManagerService(Context context, Looper looper) {
mContext = context;
- mPackageManagerInternal = Preconditions.checkNotNull(
+ mPackageManagerInternal = Objects.requireNonNull(
LocalServices.getService(PackageManagerInternal.class));
mAppOps = context.getSystemService(AppOpsManager.class);
mAssistUtils = new AssistUtils(context);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index a7cfe10..987c05f 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -42,6 +42,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -179,8 +180,8 @@
// Permission check.
checkPermissions();
// Input validation.
- Preconditions.checkNotNull(callback);
- Preconditions.checkNotNull(callback.asBinder());
+ Objects.requireNonNull(callback);
+ Objects.requireNonNull(callback.asBinder());
synchronized (this) {
// State validation.
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
index 4898e6b..43047d1 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
@@ -29,6 +29,7 @@
import com.android.internal.util.Preconditions;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -42,7 +43,7 @@
*/
public class ValidationUtil {
static void validateUuid(@Nullable String uuid) {
- Preconditions.checkNotNull(uuid);
+ Objects.requireNonNull(uuid);
Matcher matcher = UuidUtil.PATTERN.matcher(uuid);
if (!matcher.matches()) {
throw new IllegalArgumentException(
@@ -55,37 +56,37 @@
}
static void validateModel(@Nullable SoundModel model, int expectedType) {
- Preconditions.checkNotNull(model);
+ Objects.requireNonNull(model);
if (model.type != expectedType) {
throw new IllegalArgumentException("Invalid type");
}
validateUuid(model.uuid);
validateUuid(model.vendorUuid);
- Preconditions.checkNotNull(model.data);
+ Objects.requireNonNull(model.data);
}
static void validatePhraseModel(@Nullable PhraseSoundModel model) {
- Preconditions.checkNotNull(model);
+ Objects.requireNonNull(model);
validateModel(model.common, SoundModelType.KEYPHRASE);
- Preconditions.checkNotNull(model.phrases);
+ Objects.requireNonNull(model.phrases);
for (Phrase phrase : model.phrases) {
- Preconditions.checkNotNull(phrase);
+ Objects.requireNonNull(phrase);
if ((phrase.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
| RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
| RecognitionMode.GENERIC_TRIGGER)) != 0) {
throw new IllegalArgumentException("Invalid recognitionModes");
}
- Preconditions.checkNotNull(phrase.users);
- Preconditions.checkNotNull(phrase.locale);
- Preconditions.checkNotNull(phrase.text);
+ Objects.requireNonNull(phrase.users);
+ Objects.requireNonNull(phrase.locale);
+ Objects.requireNonNull(phrase.text);
}
}
static void validateRecognitionConfig(@Nullable RecognitionConfig config) {
- Preconditions.checkNotNull(config);
- Preconditions.checkNotNull(config.phraseRecognitionExtras);
+ Objects.requireNonNull(config);
+ Objects.requireNonNull(config.phraseRecognitionExtras);
for (PhraseRecognitionExtra extra : config.phraseRecognitionExtras) {
- Preconditions.checkNotNull(extra);
+ Objects.requireNonNull(extra);
if ((extra.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
| RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
| RecognitionMode.GENERIC_TRIGGER)) != 0) {
@@ -94,15 +95,15 @@
if (extra.confidenceLevel < 0 || extra.confidenceLevel > 100) {
throw new IllegalArgumentException("Invalid confidenceLevel");
}
- Preconditions.checkNotNull(extra.levels);
+ Objects.requireNonNull(extra.levels);
for (ConfidenceLevel level : extra.levels) {
- Preconditions.checkNotNull(level);
+ Objects.requireNonNull(level);
if (level.levelPercent < 0 || level.levelPercent > 100) {
throw new IllegalArgumentException("Invalid confidenceLevel");
}
}
}
- Preconditions.checkNotNull(config.data);
+ Objects.requireNonNull(config.data);
}
static void validateModelParameter(int modelParam) {
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index 0b51f9c..ecbc88f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -59,7 +59,7 @@
* @param volume Volume to check for apps.
*/
public AppCollector(Context context, @NonNull VolumeInfo volume) {
- Preconditions.checkNotNull(volume);
+ Objects.requireNonNull(volume);
mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
volume,
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 60de10c..aafadf9 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -66,6 +66,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* CacheQuotaStrategy is a strategy for determining cache quotas using usage stats and foreground
@@ -95,10 +96,10 @@
public CacheQuotaStrategy(
Context context, UsageStatsManagerInternal usageStatsManager, Installer installer,
ArrayMap<String, SparseLongArray> quotaMap) {
- mContext = Preconditions.checkNotNull(context);
- mUsageStats = Preconditions.checkNotNull(usageStatsManager);
- mInstaller = Preconditions.checkNotNull(installer);
- mQuotaMap = Preconditions.checkNotNull(quotaMap);
+ mContext = Objects.requireNonNull(context);
+ mUsageStats = Objects.requireNonNull(usageStatsManager);
+ mInstaller = Objects.requireNonNull(installer);
+ mQuotaMap = Objects.requireNonNull(quotaMap);
mPreviousValuesFile = new AtomicFile(new File(
new File(Environment.getDataDirectory(), "system"), "cachequota.xml"));
}
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index aa3ab63..f4fb93a 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -43,6 +43,7 @@
import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
+import java.util.Objects;
/**
* Controls storage sessions for users initiated by the {@link StorageManagerService}.
@@ -63,7 +64,7 @@
private volatile boolean mIsResetting;
public StorageSessionController(Context context, boolean isFuseEnabled) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mIsFuseEnabled = isFuseEnabled;
}
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 10514ad..c02ded8 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -48,6 +48,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -69,7 +70,7 @@
@GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mUserId = Preconditions.checkArgumentNonnegative(userId);
mSessionController = controller;
}
@@ -83,10 +84,10 @@
*/
public void startSession(String sessionId, ParcelFileDescriptor pfd, String upperPath,
String lowerPath) throws ExternalStorageServiceException {
- Preconditions.checkNotNull(sessionId);
- Preconditions.checkNotNull(pfd);
- Preconditions.checkNotNull(upperPath);
- Preconditions.checkNotNull(lowerPath);
+ Objects.requireNonNull(sessionId);
+ Objects.requireNonNull(pfd);
+ Objects.requireNonNull(upperPath);
+ Objects.requireNonNull(lowerPath);
prepareRemote();
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 6a986b9..5283cc4 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -62,6 +62,7 @@
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Map;
+import java.util.Objects;
import java.util.Queue;
/**
@@ -137,7 +138,7 @@
private TextClassificationConstants mSettings;
private TextClassificationManagerService(Context context) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
mLock = new Object();
mSettingsListener = new TextClassifierSettingsListener(mContext);
}
@@ -156,8 +157,8 @@
@Nullable TextClassificationSessionId sessionId,
TextSelection.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -186,8 +187,8 @@
@Nullable TextClassificationSessionId sessionId,
TextClassification.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -215,8 +216,8 @@
@Nullable TextClassificationSessionId sessionId,
TextLinks.Request request, ITextClassifierCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -244,7 +245,7 @@
public void onSelectionEvent(
@Nullable TextClassificationSessionId sessionId, SelectionEvent event)
throws RemoteException {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
final int userId = event.getUserId();
validateInput(mContext, event.getPackageName(), userId);
@@ -268,7 +269,7 @@
public void onTextClassifierEvent(
@Nullable TextClassificationSessionId sessionId,
TextClassifierEvent event) throws RemoteException {
- Preconditions.checkNotNull(event);
+ Objects.requireNonNull(event);
final String packageName = event.getEventContext() == null
? null
: event.getEventContext().getPackageName();
@@ -299,8 +300,8 @@
@Nullable TextClassificationSessionId sessionId,
TextLanguage.Request request,
ITextClassifierCallback callback) throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -329,8 +330,8 @@
@Nullable TextClassificationSessionId sessionId,
ConversationActions.Request request,
ITextClassifierCallback callback) throws RemoteException {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(callback);
final int userId = request.getUserId();
validateInput(mContext, request.getCallingPackageName(), userId);
@@ -360,8 +361,8 @@
public void onCreateTextClassificationSession(
TextClassificationContext classificationContext, TextClassificationSessionId sessionId)
throws RemoteException {
- Preconditions.checkNotNull(sessionId);
- Preconditions.checkNotNull(classificationContext);
+ Objects.requireNonNull(sessionId);
+ Objects.requireNonNull(classificationContext);
final int userId = classificationContext.getUserId();
validateInput(mContext, classificationContext.getPackageName(), userId);
@@ -391,7 +392,7 @@
@Override
public void onDestroyTextClassificationSession(TextClassificationSessionId sessionId)
throws RemoteException {
- Preconditions.checkNotNull(sessionId);
+ Objects.requireNonNull(sessionId);
synchronized (mLock) {
final int userId = mSessionUserIds.containsKey(sessionId)
@@ -514,7 +515,7 @@
UserState owningUser, int uid) {
mName = name;
mRequest =
- logOnFailure(Preconditions.checkNotNull(request), "handling pending request");
+ logOnFailure(Objects.requireNonNull(request), "handling pending request");
mOnServiceFailure =
logOnFailure(onServiceFailure, "notifying callback of service failure");
mBinder = binder;
@@ -604,8 +605,8 @@
private UserState(int userId, Context context, Object lock) {
mUserId = userId;
- mContext = Preconditions.checkNotNull(context);
- mLock = Preconditions.checkNotNull(lock);
+ mContext = Objects.requireNonNull(context);
+ mLock = Objects.requireNonNull(lock);
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 04839e1..e3b7c0a 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -103,6 +103,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
/** Manages uri grants. */
public class UriGrantsManagerService extends IUriGrantsManager.Stub {
@@ -215,7 +216,7 @@
public ParceledListSlice<android.content.UriPermission> getUriPermissions(
String packageName, boolean incoming, boolean persistedOnly) {
enforceNotIsolatedCaller("getUriPermissions");
- Preconditions.checkNotNull(packageName, "packageName");
+ Objects.requireNonNull(packageName, "packageName");
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 76d18fa..d49270d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -521,7 +521,7 @@
static final int STARTING_WINDOW_SHOWN = 1;
static final int STARTING_WINDOW_REMOVED = 2;
int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
- boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
+ private boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
// Marking the reason why this activity is being relaunched. Mainly used to track that this
// activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
@@ -1222,7 +1222,7 @@
}
ActivityStack getStack() {
- return task != null ? task.getTaskStack() : null;
+ return task != null ? task.getStack() : null;
}
@Override
@@ -1269,8 +1269,8 @@
if (getDisplayContent() != null) {
getDisplayContent().mClosingApps.remove(this);
}
- } else if (mLastParent != null && mLastParent.getTaskStack() != null) {
- task.getTaskStack().mExitingActivities.remove(this);
+ } else if (mLastParent != null && mLastParent.getStack() != null) {
+ task.getStack().mExitingActivities.remove(this);
}
final ActivityStack stack = getStack();
@@ -5523,7 +5523,7 @@
if (stack == null) {
return INVALID_DISPLAY;
}
- return stack.mDisplayId;
+ return stack.getDisplayId();
}
final boolean isDestroyable() {
@@ -7451,6 +7451,15 @@
return this == rootActivity;
}
+ void setTaskOverlay(boolean taskOverlay) {
+ mTaskOverlay = taskOverlay;
+ setAlwaysOnTop(mTaskOverlay);
+ }
+
+ boolean isTaskOverlay() {
+ return mTaskOverlay;
+ }
+
@Override
public String toString() {
if (stringName != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 16245f0..842edb3 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -310,7 +310,7 @@
int mCurrentUser;
/** The attached Display's unique identifier, or -1 if detached */
- int mDisplayId;
+ private int mDisplayId;
// Id of the previous display the stack was on.
int mPrevDisplayId = INVALID_DISPLAY;
@@ -808,8 +808,8 @@
* @return {@code true} if the windowing mode is transient, {@code false} otherwise.
*/
private static boolean isTransientWindowingMode(int windowingMode) {
- // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting
- return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ return windowingMode == WINDOWING_MODE_PINNED
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
@@ -1013,6 +1013,10 @@
return getDisplayContent();
}
+ int getDisplayId() {
+ return mDisplayId;
+ }
+
/**
* Defers updating the bounds of the stack. If the stack was resized/repositioned while
* deferring, the bounds will update in {@link #continueUpdateBounds()}.
@@ -1082,7 +1086,7 @@
}
private ActivityRecord topRunningNonOverlayTaskActivity() {
- return getActivity((r) -> (r.canBeTopRunning() && !r.mTaskOverlay));
+ return getActivity((r) -> (r.canBeTopRunning() && !r.isTaskOverlay()));
}
ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a380efc4..88b5cd3 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -571,14 +571,14 @@
}
}
- void setNextTaskIdForUserLocked(int taskId, int userId) {
+ void setNextTaskIdForUser(int taskId, int userId) {
final int currentTaskId = mCurTaskIdForUser.get(userId, -1);
if (taskId > currentTaskId) {
mCurTaskIdForUser.put(userId, taskId);
}
}
- static int nextTaskIdForUser(int taskId, int userId) {
+ private static int nextTaskIdForUser(int taskId, int userId) {
int nextTaskId = taskId + 1;
if (nextTaskId == (userId + 1) * MAX_TASK_IDS_PER_USER) {
// Wrap around as there will be smaller task ids that are available now.
@@ -587,7 +587,11 @@
return nextTaskId;
}
- int getNextTaskIdForUserLocked(int userId) {
+ int getNextTaskIdForUser() {
+ return getNextTaskIdForUser(mRootWindowContainer.mCurrentUser);
+ }
+
+ int getNextTaskIdForUser(int userId) {
final int currentTaskId = mCurTaskIdForUser.get(userId, userId * MAX_TASK_IDS_PER_USER);
// for a userId u, a taskId can only be in the range
// [u*MAX_TASK_IDS_PER_USER, (u+1)*MAX_TASK_IDS_PER_USER-1], so if MAX_TASK_IDS_PER_USER
@@ -1211,8 +1215,8 @@
}
// TODO moltmann b/136595429: Set featureId from caller
- if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
- != AppOpsManager.MODE_ALLOWED) {
+ if (mService.getAppOpsService().noteOperation(opCode, callingUid,
+ callingPackage, /* featureId */ null, false, "") != AppOpsManager.MODE_ALLOWED) {
if (!ignoreTargetSecurity) {
return ACTIVITY_RESTRICTION_APPOP;
}
@@ -1254,9 +1258,9 @@
return ACTIVITY_RESTRICTION_NONE;
}
- // TODO moltmann b/136595429: Set componentId from caller
- if (mService.getAppOpsService().noteOperation(opCode, callingUid, callingPackage, /* featureId */ null)
- != AppOpsManager.MODE_ALLOWED) {
+ // TODO moltmann b/136595429: Set featureId from caller
+ if (mService.getAppOpsService().noteOperation(opCode, callingUid,
+ callingPackage, /* featureId */ null, false, "") != AppOpsManager.MODE_ALLOWED) {
return ACTIVITY_RESTRICTION_APPOP;
}
@@ -1955,7 +1959,7 @@
// Ensure that we're not moving a task to a dynamic stack if device doesn't support
// multi-display.
- if (stack.mDisplayId != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) {
+ if (stack.getDisplayId() != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) {
throw new IllegalArgumentException("Device doesn't support multi-display, can not"
+ " reparent task=" + task + " to stackId=" + stackId);
}
@@ -2443,7 +2447,7 @@
// Handle incorrect launch/move to secondary display if needed.
if (isSecondaryDisplayPreferred) {
- final int actualDisplayId = task.getStack().mDisplayId;
+ final int actualDisplayId = task.getDisplayId();
if (!task.canBeLaunchedOnDisplay(actualDisplayId)) {
throw new IllegalStateException("Task resolved to incompatible display");
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index a2b9d95..c688612 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1073,7 +1073,8 @@
mRootWindowContainer.getTopDisplayFocusedStack();
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
true, false) + "} from uid " + callingUid + " on display "
- + (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId));
+ + (focusedStack == null ? DEFAULT_DISPLAY
+ : focusedStack.getDisplayId()));
}
}
}
@@ -1576,7 +1577,7 @@
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
- || (topTaskActivity != null && topTaskActivity.mTaskOverlay
+ || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
@@ -2044,7 +2045,7 @@
if (mOptions != null) {
if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
- r.mTaskOverlay = true;
+ r.setTaskOverlay(true);
if (!mOptions.canTaskOverlayResume()) {
final Task task = mRootWindowContainer.anyTaskForId(
mOptions.getLaunchTaskId());
@@ -2293,7 +2294,7 @@
// the same behavior as if a new instance was being started, which means not bringing it
// to the front if the caller is not itself in the front.
final boolean differentTopTask;
- if (mPreferredDisplayId == mTargetStack.mDisplayId) {
+ if (mPreferredDisplayId == mTargetStack.getDisplayId()) {
final ActivityStack focusStack = mTargetStack.getDisplay().getFocusedStack();
final ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
@@ -2343,7 +2344,7 @@
}
mMovedToFront = launchStack != launchStack.getDisplay()
.getTopStackInWindowingMode(launchStack.getWindowingMode());
- } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
+ } else if (launchStack.getDisplayId() != mTargetStack.getDisplayId()) {
// Target and computed stacks are on different displays and we've
// found a matching task - move the existing instance to that display and
// move it to front.
@@ -2392,7 +2393,7 @@
private void setNewTask(Task taskToAffiliate) {
final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
final Task task = mTargetStack.createTask(
- mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
+ mSupervisor.getNextTaskIdForUser(mStartActivity.mUserId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
@@ -2545,12 +2546,12 @@
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
canUseFocusedStack = !focusedStack.isOnHomeDisplay()
- && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
+ && r.canBeLaunchedOnDisplay(focusedStack.getDisplayId());
}
}
return canUseFocusedStack && !newTask
// Using the focus stack isn't important enough to override the preferred display.
- && (mPreferredDisplayId == focusedStack.mDisplayId);
+ && (mPreferredDisplayId == focusedStack.getDisplayId());
}
private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, Task task,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ac1dbc4..374af5a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -296,6 +296,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -901,7 +902,7 @@
boolean hasSystemAlertWindowPermission(int callingUid, int callingPid, String callingPackage) {
final int mode = getAppOpsService().noteOperation(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
- callingUid, callingPackage, /* featureId */ null);
+ callingUid, callingPackage, /* featureId */ null, false, "");
if (mode == AppOpsManager.MODE_DEFAULT) {
return checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, callingPid, callingUid)
== PERMISSION_GRANTED;
@@ -2042,8 +2043,8 @@
public int getDisplayId(IBinder activityToken) throws RemoteException {
synchronized (mGlobalLock) {
final ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
- if (stack != null && stack.mDisplayId != INVALID_DISPLAY) {
- return stack.mDisplayId;
+ if (stack != null && stack.getDisplayId() != INVALID_DISPLAY) {
+ return stack.getDisplayId();
}
return DEFAULT_DISPLAY;
}
@@ -3201,7 +3202,7 @@
final ActivityStack stack = r.getActivityStack();
final Task task = stack.createTask(
- mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), ainfo, intent,
+ mStackSupervisor.getNextTaskIdForUser(r.mUserId), ainfo, intent,
null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
@@ -4311,7 +4312,7 @@
if (params.hasSetAspectRatio()
&& !mWindowManager.isValidPictureInPictureAspectRatio(
- r.getActivityStack().mDisplayId, params.getAspectRatio())) {
+ r.getDisplayId(), params.getAspectRatio())) {
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
final float maxAspectRatio = mContext.getResources().getFloat(
@@ -6164,7 +6165,7 @@
final class LocalService extends ActivityTaskManagerInternal {
@Override
public SleepToken acquireSleepToken(String tag, int displayId) {
- Preconditions.checkNotNull(tag);
+ Objects.requireNonNull(tag);
return ActivityTaskManagerService.this.acquireSleepToken(tag, displayId);
}
@@ -6221,7 +6222,7 @@
@Override
public int startActivitiesAsPackage(String packageName, int userId, Intent[] intents,
Bundle bOptions) {
- Preconditions.checkNotNull(intents, "intents");
+ Objects.requireNonNull(intents, "intents");
final String[] resolvedTypes = new String[intents.length];
// UID of the package on user userId.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 51742b9..896147e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -600,11 +600,6 @@
private final SparseArray<ShellRoot> mShellRoots = new SparseArray<>();
- /**
- * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
- */
- private static int sNextFreeStackId = 0;
-
private RootWindowContainer mRootWindowContainer;
/**
@@ -5694,7 +5689,7 @@
@VisibleForTesting
int getNextStackId() {
- return sNextFreeStackId++;
+ return mAtmService.mStackSupervisor.getNextTaskIdForUser();
}
/**
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index d5f403f..999aab9 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -37,6 +37,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.wm.WindowManagerInternal.IDragDropCallback;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -74,7 +75,7 @@
}
void registerCallback(IDragDropCallback callback) {
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
mCallback.set(callback);
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 255ef6e..a26dfdb 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -276,7 +276,6 @@
display.getDisplayId());
mDragWindowHandle.name = "drag";
mDragWindowHandle.token = mServerChannel.getToken();
- mDragWindowHandle.layer = getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
@@ -345,12 +344,6 @@
}
}
- int getDragLayerLocked() {
- return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
/* call out to each visible window/session informing it about the drag
*/
void broadcastDragStartedLocked(final float touchX, final float touchY) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index e74f61d..55f5e28 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -156,7 +156,8 @@
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
mBehindFullscreenActivity = !mContainerShouldBeVisible;
- } else if (mContiner.isActivityTypeHome()) {
+ } else if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome()
+ && r.isRootOfTask()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner
+ " stackShouldBeVisible=" + mContainerShouldBeVisible
+ " behindFullscreenActivity=" + mBehindFullscreenActivity);
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index ebe9f08..c6183de 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -76,7 +76,6 @@
mWindowHandle.name = name;
mWindowHandle.token = mServerChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
- mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
mWindowHandle.layoutParamsFlags = 0;
mWindowHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
@@ -150,12 +149,6 @@
t.setLayer(mInputSurface, layer);
}
- private int getLayerLw(int windowType) {
- return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
void disposeChannelsLw() {
mService.mInputManager.unregisterInputChannel(mServerChannel);
mClientChannel.dispose();
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f9ff2e3..b9a9c12 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -264,7 +264,6 @@
inputWindowHandle.hasFocus = hasFocus;
inputWindowHandle.hasWallpaper = hasWallpaper;
inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
- inputWindowHandle.layer = child.mLayer;
inputWindowHandle.ownerPid = child.mSession.mPid;
inputWindowHandle.ownerUid = child.mSession.mUid;
inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
@@ -499,8 +498,7 @@
}
}
- if (mAddInputConsumerHandle
- && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+ if (mAddInputConsumerHandle) {
navInputConsumer.show(mInputTransaction, w);
mAddInputConsumerHandle = false;
}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 0beae7e..f4e608e 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -222,9 +222,7 @@
private boolean saveTaskToLaunchParam(Task task, PersistableLaunchParams params) {
final ActivityStack stack = task.getStack();
- final int displayId = stack.mDisplayId;
- final DisplayContent display =
- mSupervisor.mRootWindowContainer.getDisplayContent(displayId);
+ final DisplayContent display = stack.getDisplayContent();
final DisplayInfo info = new DisplayInfo();
display.mDisplay.getDisplayInfo(info);
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index a18d541..5df80fc 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1382,7 +1382,7 @@
// Ignore tasks from different displays
// TODO (b/115289124): No Recents on non-default displays.
- if (stack.mDisplayId != DEFAULT_DISPLAY) {
+ if (stack.getDisplayId() != DEFAULT_DISPLAY) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index f78c82b..53d7688 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -135,7 +135,7 @@
+ r + " out to bottom task " + targetTask);
} else {
targetTask = mParent.createTask(
- mParent.mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId),
+ mParent.mStackSupervisor.getNextTaskIdForUser(r.mUserId),
r.info, null /* intent */, null /* voiceSession */,
null /* voiceInteractor */, false /* toTop */);
targetTask.affinityIntent = r.intent;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 5470327..93362b9 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1495,7 +1495,7 @@
// Fallback to top focused display if the displayId is invalid.
if (displayId == INVALID_DISPLAY) {
final ActivityStack stack = getTopDisplayFocusedStack();
- displayId = stack != null ? stack.mDisplayId : DEFAULT_DISPLAY;
+ displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
}
Intent homeIntent = null;
@@ -2148,7 +2148,7 @@
// ensures that all the necessary work to migrate states in the old and new stacks
// is also done.
final Task newTask = task.getStack().createTask(
- mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), r.info,
+ mStackSupervisor.getNextTaskIdForUser(r.mUserId), r.info,
r.intent, null, null, true);
r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
@@ -2405,11 +2405,10 @@
}
private ActivityManager.StackInfo getStackInfo(ActivityStack stack) {
- final int displayId = stack.mDisplayId;
- final DisplayContent display = getDisplayContent(displayId);
+ final DisplayContent display = stack.getDisplayContent();
ActivityManager.StackInfo info = new ActivityManager.StackInfo();
stack.getBounds(info.bounds);
- info.displayId = displayId;
+ info.displayId = display.mDisplayId;
info.stackId = stack.mStackId;
info.stackToken = stack.mRemoteToken;
info.userId = stack.mCurrentUser;
@@ -2571,7 +2570,7 @@
}
ActivityStack findStackBehind(ActivityStack stack) {
- final DisplayContent display = getDisplayContent(stack.mDisplayId);
+ final DisplayContent display = getDisplayContent(stack.getDisplayId());
if (display != null) {
for (int i = display.getStackCount() - 1; i >= 0; i--) {
if (display.getStackAt(i) == stack && i > 0) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 987ecc5..06af095 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -54,6 +54,7 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
import static com.android.server.am.TaskRecordProto.ACTIVITIES;
@@ -127,7 +128,6 @@
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import android.view.Display;
import android.view.DisplayInfo;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -268,9 +268,6 @@
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
- /** Current stack. Setter must always be used to update the value. */
- private ActivityStack mStack;
-
/** The process that had previously hosted the root activity of this task.
* Used to know that we should try harder to keep this process around, in case the
* user wants to return to it. */
@@ -346,7 +343,7 @@
private final Rect mOverrideDisplayedBounds = new Rect();
/** ID of the display which rotation {@link #mRotation} has. */
- private int mLastRotationDisplayId = Display.INVALID_DISPLAY;
+ private int mLastRotationDisplayId = INVALID_DISPLAY;
/**
* Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
* moved to a new display.
@@ -678,7 +675,7 @@
if (toStack == sourceStack) {
return false;
}
- if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
+ if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
return false;
}
@@ -959,10 +956,6 @@
mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
}
- ActivityStack getStack() {
- return mStack;
- }
-
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
final ActivityStack oldStack = ((ActivityStack) oldParent);
@@ -973,8 +966,6 @@
cleanUpResourcesForDestroy();
}
- mStack = newStack;
-
super.onParentChanged(newParent, oldParent);
if (oldStack != null) {
@@ -1044,13 +1035,6 @@
mAtmService.mRootWindowContainer.invalidateTaskLayers();
}
- /**
- * @return Id of current stack, {@link ActivityTaskManager#INVALID_STACK_ID} if no stack is set.
- */
- int getStackId() {
- return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
- }
-
// Close up recents linked list.
private void closeRecentsChain() {
if (mPrevAffiliate != null) {
@@ -1261,7 +1245,7 @@
}
} else if (!mReuseTask) {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
- mStack.removeChild(this, reason);
+ getStack().removeChild(this, reason);
EventLogTags.writeWmTaskRemoved(mTaskId,
"removeChild: last r=" + r + " in t=" + this);
removeIfPossible();
@@ -1278,9 +1262,9 @@
return false;
}
if (includeFinishing) {
- return getActivity((r) -> r.mTaskOverlay) != null;
+ return getActivity((r) -> r.isTaskOverlay()) != null;
}
- return getActivity((r) -> !r.finishing && r.mTaskOverlay) != null;
+ return getActivity((r) -> !r.finishing && r.isTaskOverlay()) != null;
}
private boolean autoRemoveFromRecents() {
@@ -1296,7 +1280,7 @@
*/
private void performClearTaskAtIndexLocked(String reason) {
// Broken down into to cases to avoid object create due to capturing mStack.
- if (mStack == null) {
+ if (getStack() == null) {
forAllActivities((r) -> {
if (r.finishing) return;
// Task was restored from persistent storage.
@@ -1525,7 +1509,7 @@
private static boolean setTaskDescriptionFromActivityAboveRoot(
ActivityRecord r, ActivityRecord root, TaskDescription td) {
- if (!r.mTaskOverlay && r.taskDescription != null) {
+ if (!r.isTaskOverlay() && r.taskDescription != null) {
final TaskDescription atd = r.taskDescription;
if (td.getLabel() == null) {
td.setLabel(atd.getLabel());
@@ -1579,11 +1563,10 @@
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (!inPinnedWindowingMode() && mStack != null) {
+ if (!inPinnedWindowingMode() && getDisplayContent() != null) {
final int defaultMinSizeDp =
mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
- final DisplayContent display =
- mAtmService.mRootWindowContainer.getDisplayContent(mStack.mDisplayId);
+ final DisplayContent display = getDisplayContent();
final float density =
(float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
final int defaultMinSize = (int) (defaultMinSizeDp * density);
@@ -1820,7 +1803,7 @@
* @param bounds bounds to calculate smallestwidthdp for.
*/
private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
- DisplayContent dc = mStack.getDisplay().mDisplayContent;
+ DisplayContent dc = getDisplayContent();
if (dc != null) {
return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
}
@@ -1884,9 +1867,9 @@
if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
mTmpNonDecorBounds.set(mTmpFullBounds);
mTmpStableBounds.set(mTmpFullBounds);
- } else if (insideParentBounds && mStack != null) {
+ } else if (insideParentBounds && getDisplayContent() != null) {
final DisplayInfo di = new DisplayInfo();
- mStack.getDisplay().mDisplay.getDisplayInfo(di);
+ getDisplayContent().mDisplay.getDisplayInfo(di);
// For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
// area, i.e. the screen area without the system bars.
@@ -1997,7 +1980,7 @@
((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
final Rect parentBounds =
new Rect(newParentConfig.windowConfiguration.getBounds());
- final DisplayContent display = mStack.getDisplay();
+ final DisplayContent display = getDisplayContent();
if (display != null && display.mDisplayContent != null) {
// If a freeform window moves below system bar, there is no way to move it again
// by touch. Because its caption is covered by system bar. So we exclude them
@@ -2077,7 +2060,8 @@
/** Updates the task's bounds and override configuration to match what is expected for the
* input stack. */
void updateOverrideConfigurationForStack(ActivityStack inStack) {
- if (mStack != null && mStack == inStack) {
+ final ActivityStack stack = getStack();
+ if (stack != null && stack == inStack) {
return;
}
@@ -2101,7 +2085,8 @@
/** Returns the bounds that should be used to launch this task. */
Rect getLaunchBounds() {
- if (mStack == null) {
+ final ActivityStack stack = getStack();
+ if (stack == null) {
return null;
}
@@ -2109,9 +2094,9 @@
if (!isActivityTypeStandardOrUndefined()
|| windowingMode == WINDOWING_MODE_FULLSCREEN
|| (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
- return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
+ return isResizeable() ? stack.getRequestedOverrideBounds() : null;
} else if (!getWindowConfiguration().persistTaskBounds()) {
- return mStack.getRequestedOverrideBounds();
+ return stack.getRequestedOverrideBounds();
}
return mLastNonFullscreenBounds;
}
@@ -2134,19 +2119,32 @@
@Override
DisplayContent getDisplayContent() {
- return getTaskStack() != null ? getTaskStack().getDisplayContent() : null;
+ return getStack() != null ? getStack().getDisplayContent() : null;
}
- ActivityStack getTaskStack() {
+ int getDisplayId() {
+ final DisplayContent dc = getDisplayContent();
+ return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
+ }
+
+ ActivityStack getStack() {
return (ActivityStack) getParent();
}
+ /**
+ * @return Id of current stack, {@link ActivityTaskManager#INVALID_STACK_ID} if no stack is set.
+ */
+ int getStackId() {
+ final ActivityStack stack = getStack();
+ return stack != null ? stack.mStackId : INVALID_STACK_ID;
+ }
+
// TODO(task-hierarchy): Needs to take a generic WindowManager when task contains other tasks.
int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
int maxPosition = mChildren.size();
- if (!r.mTaskOverlay) {
+ if (!r.isTaskOverlay()) {
// We want to place all non-overlay activities below overlays.
- final ActivityRecord bottomMostOverlay = getActivity((ar) -> ar.mTaskOverlay, false);
+ final ActivityRecord bottomMostOverlay = getActivity((ar) -> ar.isTaskOverlay(), false);
if (bottomMostOverlay != null) {
maxPosition = Math.max(mChildren.indexOf(bottomMostOverlay) - 1, 0);
}
@@ -2171,7 +2169,7 @@
// No reason to defer removal of a Task that doesn't have any child.
return false;
}
- return hasWindowsAlive() && getTaskStack().isAnimating(TRANSITION | CHILDREN);
+ return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
}
@Override
@@ -2184,7 +2182,7 @@
// TODO: Consolidate this with Task.reparent()
void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
- + " from stack=" + getTaskStack());
+ + " from stack=" + getStack());
EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
position = stack.findPositionForTask(this, position, showForAllUsers());
@@ -2214,8 +2212,8 @@
@Override
public int setBounds(Rect bounds) {
int rotation = Surface.ROTATION_0;
- final DisplayContent displayContent = getTaskStack() != null
- ? getTaskStack().getDisplayContent() : null;
+ final DisplayContent displayContent = getStack() != null
+ ? getStack().getDisplayContent() : null;
if (displayContent != null) {
rotation = displayContent.getDisplayInfo().rotation;
} else if (bounds == null) {
@@ -2256,7 +2254,7 @@
void onDisplayChanged(DisplayContent dc) {
adjustBoundsForDisplayChangeIfNeeded(dc);
super.onDisplayChanged(dc);
- final int displayId = (dc != null) ? dc.getDisplayId() : Display.INVALID_DISPLAY;
+ final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
mTaskId, displayId);
}
@@ -2401,7 +2399,7 @@
/** Bounds of the task to be used for dimming, as well as touch related tests. */
public void getDimBounds(Rect out) {
- final DisplayContent displayContent = getTaskStack().getDisplayContent();
+ final DisplayContent displayContent = getStack().getDisplayContent();
// It doesn't matter if we in particular are part of the resize, since we couldn't have
// a DimLayer anyway if we weren't visible.
final boolean dockedResizing = displayContent != null
@@ -2424,9 +2422,9 @@
// stack bounds and so we don't even want to use them. Even if the app should not be
// resized the Dim should keep up with the divider.
if (dockedResizing) {
- getTaskStack().getBounds(out);
+ getStack().getBounds(out);
} else {
- getTaskStack().getBounds(mTmpRect);
+ getStack().getBounds(mTmpRect);
mTmpRect.intersect(getBounds());
out.set(mTmpRect);
}
@@ -2439,9 +2437,9 @@
void setDragResizing(boolean dragResizing, int dragResizeMode) {
if (mDragResizing != dragResizing) {
// No need to check if the mode is allowed if it's leaving dragResize
- if (dragResizing && !DragResizeMode.isModeAllowedForStack(getTaskStack(), dragResizeMode)) {
+ if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
- + getTaskStack().mStackId + " dragResizeMode=" + dragResizeMode);
+ + getStack().mStackId + " dragResizeMode=" + dragResizeMode);
}
mDragResizing = dragResizing;
mDragResizeMode = dragResizeMode;
@@ -2532,7 +2530,7 @@
*/
boolean isFloating() {
return getWindowConfiguration().tasksAreFloating()
- && !getTaskStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
+ && !getStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
@Override
@@ -2770,7 +2768,7 @@
info.userId = mUserId;
info.stackId = getStackId();
info.taskId = mTaskId;
- info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
+ info.displayId = getDisplayId();
info.isRunning = getTopNonFinishingActivity() != null;
info.baseIntent = new Intent(getBaseIntent());
info.baseActivity = mReuseActivitiesReport.base != null
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index b8f3abe..e6757e1 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -316,8 +316,8 @@
ActivityStack stack =
(displayId == INVALID_DISPLAY && task != null) ? task.getStack() : null;
if (stack != null) {
- if (DEBUG) appendLog("display-from-task=" + stack.mDisplayId);
- displayId = stack.mDisplayId;
+ if (DEBUG) appendLog("display-from-task=" + stack.getDisplayId());
+ displayId = stack.getDisplayId();
}
if (displayId == INVALID_DISPLAY && source != null) {
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index 8cff99b..20af250 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -339,7 +339,7 @@
+ userTasksDir.getAbsolutePath());
} else {
// Looks fine.
- mStackSupervisor.setNextTaskIdForUserLocked(taskId, userId);
+ mStackSupervisor.setNextTaskIdForUser(taskId, userId);
task.isPersistable = true;
tasks.add(task);
recoveredTaskIds.add(taskId);
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index a867a5d4..8bbb0d7 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -274,7 +274,6 @@
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
mDragWindowHandle.name = TAG;
mDragWindowHandle.token = mServerChannel.getToken();
- mDragWindowHandle.layer = mService.getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
@@ -450,7 +449,7 @@
}
// This is a moving or scrolling operation.
- mTask.getTaskStack().getDimBounds(mTmpRect);
+ mTask.getStack().getDimBounds(mTmpRect);
// If a target window is covered by system bar, there is no way to move it again by touch.
// So we exclude them from stack bounds. and then it will be shown inside stable area.
Rect stableBounds = new Rect();
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 5c02f46..62630a6 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1323,12 +1323,12 @@
if (includeOverlays) {
return getActivity((r) -> true);
}
- return getActivity((r) -> !r.mTaskOverlay);
+ return getActivity((r) -> !r.isTaskOverlay());
} else if (includeOverlays) {
return getActivity((r) -> !r.finishing);
}
- return getActivity((r) -> !r.finishing && !r.mTaskOverlay);
+ return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
}
void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index 74d5c04..b0c5dbc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -19,8 +19,6 @@
import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.provider.AndroidDeviceConfig;
import android.provider.DeviceConfig;
@@ -28,6 +26,7 @@
import com.android.server.wm.utils.DeviceConfigInterface;
import java.io.PrintWriter;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -74,8 +73,8 @@
WindowManagerConstants(WindowManagerGlobalLock globalLock,
Runnable updateSystemGestureExclusionCallback,
DeviceConfigInterface deviceConfig) {
- mGlobalLock = checkNotNull(globalLock);
- mUpdateSystemGestureExclusionCallback = checkNotNull(updateSystemGestureExclusionCallback);
+ mGlobalLock = Objects.requireNonNull(globalLock);
+ mUpdateSystemGestureExclusionCallback = Objects.requireNonNull(updateSystemGestureExclusionCallback);
mDeviceConfig = deviceConfig;
mListenerAndroid = this::onAndroidPropertiesChanged;
mListenerWindowManager = this::onWindowPropertiesChanged;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ab3419c..8a91d9e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -59,7 +59,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -297,6 +296,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -630,10 +630,6 @@
boolean mDisableTransitionAnimation;
- int getDragLayerLocked() {
- return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
- }
-
class RotationWatcher {
final IRotationWatcher mWatcher;
final IBinder.DeathRecipient mDeathRecipient;
@@ -2869,7 +2865,7 @@
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
- Preconditions.checkNotNull(token, "token is null");
+ Objects.requireNonNull(token, "token is null");
final int callingUid = Binder.getCallingUid();
final long origIdentity = Binder.clearCallingIdentity();
try {
@@ -4345,7 +4341,7 @@
final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
return (focusedApp != null && focusedApp.getTask() != null)
- ? focusedApp.getTask().getTaskStack() : null;
+ ? focusedApp.getTask().getStack() : null;
}
public boolean detectSafeMode() {
@@ -7664,7 +7660,7 @@
return;
}
- final ActivityStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getStack();
// We ignore home stack since we don't want home stack to move to front when touched.
// Specifically, in freeform we don't want tapping on home to cause the freeform apps to go
// behind home. See b/117376413
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bb7c26c..b681923 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1287,7 +1287,7 @@
// notify the client of frame changes in this case. Not only is it a lot of churn, but
// the frame may not correspond to the surface size or the onscreen area at various
// phases in the animation, and the client will become sad and confused.
- if (task != null && task.getTaskStack().isAnimatingBounds()) {
+ if (task != null && task.getStack().isAnimatingBounds()) {
return;
}
@@ -1427,8 +1427,8 @@
ActivityStack getStack() {
Task task = getTask();
if (task != null) {
- if (task.getTaskStack() != null) {
- return task.getTaskStack();
+ if (task.getStack() != null) {
+ return task.getStack();
}
}
// Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
@@ -1447,7 +1447,7 @@
bounds.setEmpty();
mTmpRect.setEmpty();
if (intersectWithStackBounds) {
- final ActivityStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getStack();
if (stack != null) {
stack.getDimBounds(mTmpRect);
} else {
@@ -1879,8 +1879,8 @@
final int top = mWindowFrames.mFrame.top;
final Task task = getTask();
final boolean adjustedForMinimizedDockOrIme = task != null
- && (task.getTaskStack().isAdjustedForMinimizedDockedStack()
- || task.getTaskStack().isAdjustedForIme());
+ && (task.getStack().isAdjustedForMinimizedDockedStack()
+ || task.getStack().isAdjustedForIme());
if (mToken.okToAnimate()
&& (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& !isDragResizing() && !adjustedForMinimizedDockOrIme
@@ -1916,7 +1916,7 @@
boolean isObscuringDisplay() {
Task task = getTask();
- if (task != null && task.getTaskStack() != null && !task.getTaskStack().fillsParent()) {
+ if (task != null && task.getStack() != null && !task.getStack().fillsParent()) {
return false;
}
return isOpaqueDrawn() && fillsDisplay();
@@ -2349,8 +2349,8 @@
void applyAdjustForImeIfNeeded() {
final Task task = getTask();
- if (task != null && task.getTaskStack() != null && task.getTaskStack().isAdjustedForIme()) {
- task.getTaskStack().applyAdjustForImeIfNeeded(task);
+ if (task != null && task.getStack() != null && task.getStack().isAdjustedForIme()) {
+ task.getStack().applyAdjustForImeIfNeeded(task);
}
}
@@ -2694,7 +2694,7 @@
return false;
}
- return mActivityRecord.getTask().getTaskStack().shouldIgnoreInput()
+ return mActivityRecord.getTask().getStack().shouldIgnoreInput()
|| !mActivityRecord.mVisibleRequested
|| isRecentsAnimationConsumingAppInput();
}
@@ -3214,7 +3214,7 @@
return;
}
- final ActivityStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getStack();
if (stack == null) {
return;
}
@@ -3228,7 +3228,7 @@
return;
}
- final ActivityStack stack = task.getTaskStack();
+ final ActivityStack stack = task.getStack();
if (stack == null) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 175fccb..1a11766 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -888,10 +888,10 @@
int posX = 0;
int posY = 0;
- task.getTaskStack().getDimBounds(mTmpStackBounds);
+ task.getStack().getDimBounds(mTmpStackBounds);
boolean allowStretching = false;
- task.getTaskStack().getFinalAnimationSourceHintBounds(mTmpSourceBounds);
+ task.getStack().getFinalAnimationSourceHintBounds(mTmpSourceBounds);
// If we don't have source bounds, we can attempt to use the content insets
// in the following scenario:
// 1. We have content insets.
@@ -901,8 +901,8 @@
// because of the force-scale until resize state.
if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
|| mWin.mLastRelayoutContentInsets.height() > 0)
- && !task.getTaskStack().lastAnimatingBoundsWasToFullscreen()) {
- mTmpSourceBounds.set(task.getTaskStack().mPreAnimationBounds);
+ && !task.getStack().lastAnimatingBoundsWasToFullscreen()) {
+ mTmpSourceBounds.set(task.getStack().mPreAnimationBounds);
mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
allowStretching = true;
}
@@ -916,7 +916,7 @@
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
- task.getTaskStack().getFinalAnimationBounds(mTmpAnimatingBounds);
+ task.getStack().getFinalAnimationBounds(mTmpAnimatingBounds);
// Calculate the current progress and interpolate the difference between the target
// and source bounds
@@ -1495,7 +1495,7 @@
*/
boolean isForceScaled() {
final Task task = mWin.getTask();
- if (task != null && task.getTaskStack().isForceScaled()) {
+ if (task != null && task.getStack().isForceScaled()) {
return true;
}
return mForceScaleUntilResize;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1536816..9163f16 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -215,6 +215,7 @@
import android.provider.ContactsInternal;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.provider.Telephony;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@@ -303,6 +304,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -2266,23 +2268,23 @@
@VisibleForTesting
DevicePolicyManagerService(Injector injector) {
mInjector = injector;
- mContext = Preconditions.checkNotNull(injector.mContext);
- mHandler = new Handler(Preconditions.checkNotNull(injector.getMyLooper()));
+ mContext = Objects.requireNonNull(injector.mContext);
+ mHandler = new Handler(Objects.requireNonNull(injector.getMyLooper()));
mConstantsObserver = new DevicePolicyConstantsObserver(mHandler);
mConstantsObserver.register();
mConstants = loadConstants();
- mOwners = Preconditions.checkNotNull(injector.newOwners());
+ mOwners = Objects.requireNonNull(injector.newOwners());
- mUserManager = Preconditions.checkNotNull(injector.getUserManager());
- mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
- mUsageStatsManagerInternal = Preconditions.checkNotNull(
+ mUserManager = Objects.requireNonNull(injector.getUserManager());
+ mUserManagerInternal = Objects.requireNonNull(injector.getUserManagerInternal());
+ mUsageStatsManagerInternal = Objects.requireNonNull(
injector.getUsageStatsManagerInternal());
- mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
- mIPlatformCompat = Preconditions.checkNotNull(injector.getIPlatformCompat());
- mIPermissionManager = Preconditions.checkNotNull(injector.getIPermissionManager());
- mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
+ mIPackageManager = Objects.requireNonNull(injector.getIPackageManager());
+ mIPlatformCompat = Objects.requireNonNull(injector.getIPlatformCompat());
+ mIPermissionManager = Objects.requireNonNull(injector.getIPermissionManager());
+ mTelephonyManager = Objects.requireNonNull(injector.getTelephonyManager());
mLocalService = new LocalService();
mLockPatternUtils = injector.newLockPatternUtils();
@@ -4047,7 +4049,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
+ Objects.requireNonNull(adminReceiver, "ComponentName is null");
enforceShell("forceRemoveActiveAdmin");
mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
@@ -4164,7 +4166,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
validateQualityConstant(quality);
final int userId = mInjector.userHandleGetCallingUserId();
@@ -4377,7 +4379,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4419,7 +4421,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4451,7 +4453,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -4633,7 +4635,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
final ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4663,7 +4665,7 @@
@Override
public void setPasswordMinimumLowerCase(ComponentName who, int length, boolean parent) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4696,7 +4698,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4728,7 +4730,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4760,7 +4762,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4792,7 +4794,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -5019,7 +5021,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
// This API can only be called by an active device admin,
@@ -5259,7 +5261,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
final ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -5360,7 +5362,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
// timeoutMs with value 0 means that the admin doesn't participate
// timeoutMs is clamped to the interval in case the internal constants change in the future
@@ -6108,7 +6110,7 @@
@Override
public void setDelegatedScopes(ComponentName who, String delegatePackage,
List<String> scopeList) throws SecurityException {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(delegatePackage, "Delegate package is null or empty");
Preconditions.checkCollectionElementsNotNull(scopeList, "Scopes");
// Remove possible duplicates.
@@ -6206,7 +6208,7 @@
@NonNull
public List<String> getDelegatedScopes(ComponentName who,
String delegatePackage) throws SecurityException {
- Preconditions.checkNotNull(delegatePackage, "Delegate package is null");
+ Objects.requireNonNull(delegatePackage, "Delegate package is null");
// Retrieve the user ID of the calling process.
final int callingUid = mInjector.binderGetCallingUid();
@@ -6246,8 +6248,8 @@
@NonNull
public List<String> getDelegatePackages(ComponentName who, String scope)
throws SecurityException {
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(scope, "Scope is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(scope, "Scope is null");
if (!Arrays.asList(DELEGATIONS).contains(scope)) {
throw new IllegalArgumentException("Unexpected delegation scope: " + scope);
}
@@ -6329,7 +6331,7 @@
* @return {@code true} if the calling process is a delegate of {@code scope}.
*/
private boolean isCallerDelegate(String callerPackage, int callerUid, String scope) {
- Preconditions.checkNotNull(callerPackage, "callerPackage is null");
+ Objects.requireNonNull(callerPackage, "callerPackage is null");
if (!Arrays.asList(DELEGATIONS).contains(scope)) {
throw new IllegalArgumentException("Unexpected delegation scope: " + scope);
}
@@ -6410,7 +6412,7 @@
*/
private void setDelegatedScopePreO(ComponentName who,
String delegatePackage, String scope) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -6938,7 +6940,7 @@
return null;
}
synchronized (getLockObject()) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// Only check if system user has set global proxy. We don't allow other users to set it.
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
@@ -7066,7 +7068,7 @@
if (!mHasFeature) {
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
// Check for permissions
@@ -7220,7 +7222,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
@@ -7287,7 +7289,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -7347,7 +7349,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// TODO (b/145286957) Refactor security checks
enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
@@ -7369,7 +7371,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
@@ -7383,7 +7385,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// TODO (b/145286957) Refactor security checks
enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
@@ -7405,7 +7407,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
@@ -7416,7 +7418,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// Allow setting this policy to true only if there is a split system user.
if (forceEphemeralUsers && !mInjector.userManagerIsSplitSystemUser()) {
throw new UnsupportedOperationException(
@@ -7443,7 +7445,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -7472,7 +7474,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// TODO: If an unaffiliated user is removed, the admin will be able to request a bugreport
// which could still contain data related to that user. Should we disallow that, e.g. until
@@ -7709,7 +7711,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
@@ -7779,7 +7781,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
if (isManagedProfile(userHandle)) {
if (parent) {
@@ -7867,7 +7869,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(packageList, "packageList is null");
+ Objects.requireNonNull(packageList, "packageList is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
// Ensure the caller is a DO or a keep uninstalled packages delegate.
@@ -8104,7 +8106,7 @@
@Override
public void clearDeviceOwner(String packageName) {
- Preconditions.checkNotNull(packageName, "packageName is null");
+ Objects.requireNonNull(packageName, "packageName is null");
final int callingUid = mInjector.binderGetCallingUid();
try {
int uid = mInjector.getPackageManager().getPackageUidAsUser(packageName,
@@ -8259,7 +8261,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
enforceNotManagedProfile(userId, "clear profile owner");
@@ -8300,7 +8302,7 @@
@Override
public void setDeviceOwnerLockScreenInfo(ComponentName who, CharSequence info) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
if (!mHasFeature) {
return;
}
@@ -8470,7 +8472,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8497,7 +8499,7 @@
@Override
public void setProfileName(ComponentName who, String profileName) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceProfileOrDeviceOwner(who);
final int userId = UserHandle.getCallingUserId();
@@ -9090,7 +9092,7 @@
@Override
public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9116,7 +9118,7 @@
@Override
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9135,7 +9137,7 @@
@Override
public void setDefaultSmsApplication(ComponentName admin, String packageName) {
- Preconditions.checkNotNull(admin, "ComponentName is null");
+ Objects.requireNonNull(admin, "ComponentName is null");
enforceDeviceOwner(admin);
mInjector.binderWithCleanCallingIdentity(() ->
SmsApplication.setDefaultApplication(packageName, mContext));
@@ -9190,8 +9192,8 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- Preconditions.checkNotNull(admin, "admin is null");
- Preconditions.checkNotNull(agent, "agent is null");
+ Objects.requireNonNull(admin, "admin is null");
+ Objects.requireNonNull(agent, "agent is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
@@ -9207,7 +9209,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return null;
}
- Preconditions.checkNotNull(agent, "agent null");
+ Objects.requireNonNull(agent, "agent null");
enforceFullCrossUsersPermission(userHandle);
synchronized (getLockObject()) {
@@ -9259,7 +9261,7 @@
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9281,7 +9283,7 @@
@Override
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9330,7 +9332,7 @@
@Override
public void clearCrossProfileIntentFilters(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9407,7 +9409,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
if (packageList != null) {
int userId = UserHandle.getCallingUserId();
@@ -9460,7 +9462,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -9536,7 +9538,7 @@
if (!mHasFeature) {
return true;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(packageName, "packageName is null");
enforceSystemCaller("query if an accessibility service is disabled by admin");
@@ -9587,7 +9589,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (packageList != null) {
List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
@@ -9627,7 +9629,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -9681,7 +9683,7 @@
if (!mHasFeature) {
return true;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(packageName, "packageName is null");
enforceSystemCaller("query if an input method is disabled by admin");
@@ -9704,7 +9706,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (!isManagedProfile(callingUserId)) {
@@ -9725,7 +9727,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -9787,8 +9789,8 @@
@Override
public UserHandle createAndManageUser(ComponentName admin, String name,
ComponentName profileOwner, PersistableBundle adminExtras, int flags) {
- Preconditions.checkNotNull(admin, "admin is null");
- Preconditions.checkNotNull(profileOwner, "profileOwner is null");
+ Objects.requireNonNull(admin, "admin is null");
+ Objects.requireNonNull(profileOwner, "profileOwner is null");
if (!admin.getPackageName().equals(profileOwner.getPackageName())) {
throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin "
+ admin + " are not in the same package");
@@ -9919,8 +9921,8 @@
@Override
public boolean removeUser(ComponentName who, UserHandle userHandle) {
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(userHandle, "UserHandle is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(userHandle, "UserHandle is null");
enforceDeviceOwner(who);
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -9953,7 +9955,7 @@
@Override
public boolean switchUser(ComponentName who, UserHandle userHandle) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -9976,8 +9978,8 @@
@Override
public int startUserInBackground(ComponentName who, UserHandle userHandle) {
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(userHandle, "UserHandle is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(userHandle, "UserHandle is null");
enforceDeviceOwner(who);
final int userId = userHandle.getIdentifier();
@@ -10008,8 +10010,8 @@
@Override
public int stopUser(ComponentName who, UserHandle userHandle) {
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(userHandle, "UserHandle is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(userHandle, "UserHandle is null");
enforceDeviceOwner(who);
final int userId = userHandle.getIdentifier();
@@ -10023,7 +10025,7 @@
@Override
public int logoutUser(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int callingUserId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -10077,7 +10079,7 @@
@Override
public List<UserHandle> getSecondaryUsers(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -10096,7 +10098,7 @@
@Override
public boolean isEphemeralUser(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceProfileOrDeviceOwner(who);
final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -10178,7 +10180,7 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner,
boolean parent) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
@@ -10324,7 +10326,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
final ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who,
@@ -10559,7 +10561,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10653,7 +10655,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10674,7 +10676,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10696,7 +10698,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10717,7 +10719,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10797,7 +10799,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10818,7 +10820,7 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10840,8 +10842,8 @@
@Override
public void setLockTaskPackages(ComponentName who, String[] packages)
throws SecurityException {
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(packages, "packages is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(packages, "packages is null");
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
@@ -10861,7 +10863,7 @@
@Override
public String[] getLockTaskPackages(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier();
synchronized (getLockObject()) {
@@ -10881,7 +10883,7 @@
@Override
public void setLockTaskFeatures(ComponentName who, int flags) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
// Throw if Overview is used without Home.
boolean hasHome = (flags & LOCK_TASK_FEATURE_HOME) != 0;
@@ -10908,7 +10910,7 @@
@Override
public int getLockTaskFeatures(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(who);
@@ -10978,7 +10980,7 @@
@Override
public void setGlobalSetting(ComponentName who, String setting, String value) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_GLOBAL_SETTING)
@@ -11018,7 +11020,7 @@
@Override
public void setSystemSetting(ComponentName who, String setting, String value) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
synchronized (getLockObject()) {
@@ -11038,7 +11040,7 @@
@Override
public void setLocationEnabled(ComponentName who, boolean locationEnabled) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
UserHandle userHandle = mInjector.binderGetCallingUserHandle();
@@ -11057,7 +11059,7 @@
@Override
public boolean setTime(ComponentName who, long millis) {
- Preconditions.checkNotNull(who, "ComponentName is null in setTime");
+ Objects.requireNonNull(who, "ComponentName is null in setTime");
enforceDeviceOwner(who);
// Don't allow set time when auto time is on.
if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) == 1) {
@@ -11072,7 +11074,7 @@
@Override
public boolean setTimeZone(ComponentName who, String timeZone) {
- Preconditions.checkNotNull(who, "ComponentName is null in setTimeZone");
+ Objects.requireNonNull(who, "ComponentName is null in setTimeZone");
enforceDeviceOwner(who);
// Don't allow set timezone when auto timezone is on.
if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) {
@@ -11088,7 +11090,7 @@
@Override
public void setSecureSetting(ComponentName who, String setting, String value) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
int callingUserId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -11159,7 +11161,7 @@
@Override
public void setMasterVolumeMuted(ComponentName who, boolean on) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
@@ -11173,7 +11175,7 @@
@Override
public boolean isMasterVolumeMuted(ComponentName who) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -11186,7 +11188,7 @@
@Override
public void setUserIcon(ComponentName who, Bitmap icon) {
synchronized (getLockObject()) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
@@ -11201,7 +11203,7 @@
@Override
public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -11664,7 +11666,7 @@
@Override
public Intent createAdminSupportIntent(String restriction) {
- Preconditions.checkNotNull(restriction);
+ Objects.requireNonNull(restriction);
final int uid = mInjector.binderGetCallingUid();
final int userId = UserHandle.getUserId(uid);
Intent intent = null;
@@ -11922,7 +11924,7 @@
@Override
public SystemUpdateInfo getPendingSystemUpdate(ComponentName admin) {
- Preconditions.checkNotNull(admin, "ComponentName is null");
+ Objects.requireNonNull(admin, "ComponentName is null");
enforceProfileOrDeviceOwner(admin);
return mOwners.getSystemUpdateInfo();
@@ -11964,7 +11966,7 @@
public void setPermissionGrantState(ComponentName admin, String callerPackage,
String packageName, String permission, int grantState, RemoteCallback callback)
throws RemoteException {
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
UserHandle user = mInjector.binderGetCallingUserHandle();
synchronized (getLockObject()) {
@@ -12099,7 +12101,7 @@
@Override
public boolean isProvisioningAllowed(String action, String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
final int callingUid = mInjector.binderGetCallingUid();
final long ident = mInjector.binderClearCallingIdentity();
@@ -12119,7 +12121,7 @@
@Override
public int checkProvisioningPreCondition(String action, String packageName) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
enforceCanManageProfileAndDeviceOwners();
return checkProvisioningPreConditionSkipPermission(action, packageName);
}
@@ -12359,7 +12361,7 @@
@Override
public void reboot(ComponentName admin) {
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
// Make sure caller has DO.
enforceDeviceOwner(admin);
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -12380,7 +12382,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
@@ -12400,7 +12402,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
return admin.shortSupportMessage;
@@ -12412,7 +12414,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
@@ -12432,7 +12434,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
return admin.longSupportMessage;
@@ -12444,7 +12446,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceSystemCaller("query support message for user");
synchronized (getLockObject()) {
@@ -12461,7 +12463,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceSystemCaller("query support message for user");
synchronized (getLockObject()) {
@@ -12478,7 +12480,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
enforceManagedProfile(userHandle, "set organization color");
synchronized (getLockObject()) {
@@ -12513,7 +12515,7 @@
if (!mHasFeature) {
return ActiveAdmin.DEF_ORGANIZATION_COLOR;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -12542,7 +12544,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
@@ -12561,7 +12563,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -12599,8 +12601,8 @@
@Override
public List<String> setMeteredDataDisabledPackages(ComponentName who, List<String> packageNames) {
- Preconditions.checkNotNull(who);
- Preconditions.checkNotNull(packageNames);
+ Objects.requireNonNull(who);
+ Objects.requireNonNull(packageNames);
if (!mHasFeature) {
return packageNames;
@@ -12646,7 +12648,7 @@
@Override
public List<String> getMeteredDataDisabledPackages(ComponentName who) {
- Preconditions.checkNotNull(who);
+ Objects.requireNonNull(who);
if (!mHasFeature) {
return new ArrayList<>();
@@ -12662,7 +12664,7 @@
@Override
public boolean isMeteredDataDisabledPackageForUser(ComponentName who,
String packageName, int userId) {
- Preconditions.checkNotNull(who);
+ Objects.requireNonNull(who);
if (!mHasFeature) {
return false;
@@ -12688,7 +12690,7 @@
public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
// As the caller is the system, it must specify the component name of the profile owner
// as a sanity / safety check.
- Preconditions.checkNotNull(who);
+ Objects.requireNonNull(who);
if (!mHasFeature) {
return;
@@ -12808,7 +12810,7 @@
return Collections.emptyList();
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return new ArrayList<String>(
@@ -12877,7 +12879,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -12907,7 +12909,7 @@
synchronized (getLockObject()) {
if (!isCallerWithSystemUid()) {
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
}
return mInjector.securityLogGetLoggingEnabledProperty();
@@ -12931,7 +12933,7 @@
return null;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
ensureDeviceOwnerAndAllUsersAffiliated(admin);
DevicePolicyEventLogger
@@ -12961,7 +12963,7 @@
return null;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
ensureDeviceOwnerAndAllUsersAffiliated(admin);
if (!mInjector.securityLogGetLoggingEnabledProperty()) {
@@ -13206,7 +13208,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
enforceProfileOrDeviceOwner(admin);
int userId = mInjector.userHandleGetCallingUserId();
toggleBackupServiceActive(userId, enabled);
@@ -13214,7 +13216,7 @@
@Override
public boolean isBackupServiceEnabled(ComponentName admin) {
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
if (!mHasFeature) {
return true;
}
@@ -13239,14 +13241,14 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkNotNull(admin);
- Preconditions.checkNotNull(caller);
- Preconditions.checkNotNull(serviceIntent);
+ Objects.requireNonNull(admin);
+ Objects.requireNonNull(caller);
+ Objects.requireNonNull(serviceIntent);
Preconditions.checkArgument(
serviceIntent.getComponent() != null || serviceIntent.getPackage() != null,
"Service intent must be explicit (with a package name or component): "
+ serviceIntent);
- Preconditions.checkNotNull(connection);
+ Objects.requireNonNull(connection);
Preconditions.checkArgument(mInjector.userHandleGetCallingUserId() != targetUserId,
"target user id must be different from the calling user id");
@@ -13290,7 +13292,7 @@
if (!mHasFeature) {
return Collections.emptyList();
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -13755,7 +13757,7 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return false;
}
- Preconditions.checkNotNull(token);
+ Objects.requireNonNull(token);
synchronized (getLockObject()) {
final int userHandle = mInjector.userHandleGetCallingUserId();
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -13791,9 +13793,9 @@
@Override
public void clearApplicationUserData(ComponentName admin, String packageName,
IPackageDataObserver callback) {
- Preconditions.checkNotNull(admin, "ComponentName is null");
- Preconditions.checkNotNull(packageName, "packageName is null");
- Preconditions.checkNotNull(callback, "callback is null");
+ Objects.requireNonNull(admin, "ComponentName is null");
+ Objects.requireNonNull(packageName, "packageName is null");
+ Objects.requireNonNull(callback, "callback is null");
enforceProfileOrDeviceOwner(admin);
final int userId = UserHandle.getCallingUserId();
@@ -13824,7 +13826,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
ActiveAdmin deviceOwner =
@@ -13865,8 +13867,8 @@
return;
}
- Preconditions.checkNotNull(admin, "Admin cannot be null.");
- Preconditions.checkNotNull(target, "Target cannot be null.");
+ Objects.requireNonNull(admin, "Admin cannot be null.");
+ Objects.requireNonNull(target, "Target cannot be null.");
enforceProfileOrDeviceOwner(admin);
@@ -14001,7 +14003,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
final String startUserSessionMessageString =
startUserSessionMessage != null ? startUserSessionMessage.toString() : null;
@@ -14026,7 +14028,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
final String endUserSessionMessageString =
endUserSessionMessage != null ? endUserSessionMessage.toString() : null;
@@ -14051,7 +14053,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
@@ -14065,7 +14067,7 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkNotNull(admin);
+ Objects.requireNonNull(admin);
synchronized (getLockObject()) {
final ActiveAdmin deviceOwner =
@@ -14108,22 +14110,18 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return -1;
}
- Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
- Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
+ Objects.requireNonNull(who, "ComponentName is null in addOverrideApn");
+ Objects.requireNonNull(apnSetting, "ApnSetting is null in addOverrideApn");
enforceDeviceOwner(who);
- int operatedId = -1;
- Uri resultUri = mInjector.binderWithCleanCallingIdentity(() ->
- mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues()));
- if (resultUri != null) {
- try {
- operatedId = Integer.parseInt(resultUri.getLastPathSegment());
- } catch (NumberFormatException e) {
- Slog.e(LOG_TAG, "Failed to parse inserted override APN id.", e);
- }
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.addDevicePolicyOverrideApn(mContext, apnSetting));
+ } else {
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to add override apn");
+ return Telephony.Carriers.INVALID_APN_ID;
}
-
- return operatedId;
}
@Override
@@ -14132,17 +14130,21 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
- Preconditions.checkNotNull(apnSetting, "ApnSetting is null in updateOverrideApn");
+ Objects.requireNonNull(who, "ComponentName is null in updateOverrideApn");
+ Objects.requireNonNull(apnSetting, "ApnSetting is null in updateOverrideApn");
enforceDeviceOwner(who);
if (apnId < 0) {
return false;
}
- return mInjector.binderWithCleanCallingIdentity(() ->
- mContext.getContentResolver().update(
- Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
- apnSetting.toContentValues(), null, null) > 0);
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.modifyDevicePolicyOverrideApn(mContext, apnId, apnSetting));
+ } else {
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to modify override apn");
+ return false;
+ }
}
@Override
@@ -14150,7 +14152,7 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
+ Objects.requireNonNull(who, "ComponentName is null in removeOverrideApn");
enforceDeviceOwner(who);
return removeOverrideApnUnchecked(apnId);
@@ -14171,30 +14173,20 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return Collections.emptyList();
}
- Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
+ Objects.requireNonNull(who, "ComponentName is null in getOverrideApns");
enforceDeviceOwner(who);
return getOverrideApnsUnchecked();
}
private List<ApnSetting> getOverrideApnsUnchecked() {
- final Cursor cursor = mInjector.binderWithCleanCallingIdentity(
- () -> mContext.getContentResolver().query(DPC_URI, null, null, null, null));
-
- if (cursor == null) {
- return Collections.emptyList();
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm != null) {
+ return mInjector.binderWithCleanCallingIdentity(
+ () -> tm.getDevicePolicyOverrideApns(mContext));
}
- try {
- List<ApnSetting> apnList = new ArrayList<ApnSetting>();
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- ApnSetting apn = ApnSetting.makeApnSetting(cursor);
- apnList.add(apn);
- }
- return apnList;
- } finally {
- cursor.close();
- }
+ Log.w(LOG_TAG, "TelephonyManager is null when trying to get override apns");
+ return Collections.emptyList();
}
@Override
@@ -14202,7 +14194,7 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
+ Objects.requireNonNull(who, "ComponentName is null in setOverrideApnEnabled");
enforceDeviceOwner(who);
setOverrideApnsEnabledUnchecked(enabled);
@@ -14220,7 +14212,7 @@
if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
- Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
+ Objects.requireNonNull(who, "ComponentName is null in isOverrideApnEnabled");
enforceDeviceOwner(who);
Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity(
@@ -14304,7 +14296,7 @@
return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
final int returnCode;
@@ -14342,7 +14334,7 @@
return PRIVATE_DNS_MODE_UNKNOWN;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
String currentMode = mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE);
if (currentMode == null) {
@@ -14366,7 +14358,7 @@
return null;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
enforceDeviceOwner(who);
return mInjector.settingsGlobalGetString(PRIVATE_DNS_SPECIFIER);
@@ -14404,7 +14396,7 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -14425,7 +14417,7 @@
if (!mHasFeature) {
return Collections.emptyList();
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -14479,8 +14471,8 @@
if (!mHasFeature) {
return;
}
- Preconditions.checkNotNull(who, "ComponentName is null");
- Preconditions.checkNotNull(packageNames, "Package names is null");
+ Objects.requireNonNull(who, "ComponentName is null");
+ Objects.requireNonNull(packageNames, "Package names is null");
synchronized (getLockObject()) {
final ActiveAdmin admin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -14494,7 +14486,7 @@
if (!mHasFeature) {
return Collections.emptyList();
}
- Preconditions.checkNotNull(who, "ComponentName is null");
+ Objects.requireNonNull(who, "ComponentName is null");
synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
index dd3bfc3..4b66bea 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
@@ -39,6 +39,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.Objects;
/**
* Handles reading and writing of the owner transfer metadata file.
@@ -185,8 +186,8 @@
@NonNull int userId, @NonNull String adminType) {
this.sourceComponent = sourceComponent;
this.targetComponent = targetComponent;
- Preconditions.checkNotNull(sourceComponent);
- Preconditions.checkNotNull(targetComponent);
+ Objects.requireNonNull(sourceComponent);
+ Objects.requireNonNull(targetComponent);
Preconditions.checkStringNotEmpty(adminType);
this.userId = userId;
this.adminType = adminType;
@@ -199,7 +200,7 @@
}
private static ComponentName unflattenComponentUnchecked(String flatComponent) {
- Preconditions.checkNotNull(flatComponent);
+ Objects.requireNonNull(flatComponent);
return ComponentName.unflattenFromString(flatComponent);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 529339e..0504d14 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -48,6 +48,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.parsing.AndroidPackage;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -68,6 +69,7 @@
import org.mockito.quality.Strictness;
import java.io.File;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -138,11 +140,15 @@
.spyStatic(Settings.Global.class)
.startMocking();
- // Mock LocalServices.getService(PackageManagerInternal.class).getApplicationInfo dependency
+ // Mock LocalServices.getService(PackageManagerInternal.class).getPackage dependency
// needed by AppOpsService
PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class);
- when(mockPackageManagerInternal.getApplicationInfo(eq(sMyPackageName), anyInt(), anyInt(),
- anyInt())).thenReturn(sContext.getApplicationInfo());
+ AndroidPackage mockMyPkg = mock(AndroidPackage.class);
+ when(mockMyPkg.isPrivileged()).thenReturn(false);
+ when(mockMyPkg.getUid()).thenReturn(mMyUid);
+ when(mockMyPkg.getFeatures()).thenReturn(Collections.emptyList());
+
+ when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
doReturn(mockPackageManagerInternal).when(
() -> LocalServices.getService(PackageManagerInternal.class));
@@ -162,12 +168,12 @@
mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
// Note an op that's allowed.
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
// Note another op that's not allowed.
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
@@ -183,16 +189,16 @@
// This op controls WIFI_SCAN
mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);
- assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
+ null)).isEqualTo(MODE_ALLOWED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
// Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
- assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ERRORED);
+ assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
+ null)).isEqualTo(MODE_ERRORED);
assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
@@ -203,8 +209,8 @@
public void testStatePersistence() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
- mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
+ mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
mAppOpsService.writeState();
// Create a new app ops service, and initialize its state from XML.
@@ -221,7 +227,7 @@
@Test
public void testShutdown() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
mAppOpsService.shutdown();
// Create a new app ops service, and initialize its state from XML.
@@ -236,7 +242,7 @@
@Test
public void testGetOpsForPackage() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
// Query all ops
List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
@@ -265,7 +271,7 @@
@Test
public void testPackageRemoved() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -278,7 +284,7 @@
@Test
public void testPackageRemovedHistoricalOps() throws InterruptedException {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName,
@@ -317,7 +323,7 @@
@Test
public void testUidRemoved() {
mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
- mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null);
+ mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
List<PackageOps> loggedOps = getLoggedOps();
assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
@@ -340,13 +346,13 @@
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -354,8 +360,8 @@
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -363,13 +369,13 @@
setupProcStateTests();
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -378,13 +384,13 @@
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isEqualTo(MODE_ALLOWED);
}
@Test
@@ -393,13 +399,13 @@
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -407,8 +413,8 @@
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
}
@Test
@@ -417,13 +423,13 @@
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
@@ -431,8 +437,8 @@
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isEqualTo(MODE_ALLOWED);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -440,8 +446,8 @@
Thread.sleep(50);
mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
ActivityManager.PROCESS_CAPABILITY_NONE);
- assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
- .isNotEqualTo(MODE_ALLOWED);
+ assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
+ false, null)).isNotEqualTo(MODE_ALLOWED);
}
private List<PackageOps> getLoggedOps() {
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d34f783..bbc6bdb 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -26,6 +26,11 @@
<option name="test-file-name" value="SimpleServiceTestApp.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="AppIntegrityManagerServiceTestApp.apk->/data/local/tmp/AppIntegrityManagerServiceTestApp.apk" />
+ </target_preparer>
+
<option name="test-tag" value="FrameworksServicesTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.servicestests" />
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
deleted file mode 100644
index 6345c98..0000000
--- a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
+++ /dev/null
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 2ce17a1..f8bcff5 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -485,7 +485,7 @@
@Test
public void testDispatchUids_dispatchNeededChanges() throws RemoteException {
when(mAppOpsService.noteOperation(AppOpsManager.OP_GET_USAGE_STATS, Process.myUid(), null,
- null)).thenReturn(AppOpsManager.MODE_ALLOWED);
+ null, false, null)).thenReturn(AppOpsManager.MODE_ALLOWED);
final int[] changesToObserve = {
ActivityManager.UID_OBSERVER_PROCSTATE,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 1a67576..960f670 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -217,6 +217,8 @@
return mMockSystemServices.wifiManager;
case Context.ACCOUNT_SERVICE:
return mMockSystemServices.accountManager;
+ case Context.TELEPHONY_SERVICE:
+ return mMockSystemServices.telephonyManager;
}
throw new UnsupportedOperationException();
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 17e5832..09a6819 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -17,7 +17,6 @@
import com.google.common.base.Objects;
-import com.android.internal.util.Preconditions;
import com.android.server.pm.UserRestrictionsUtils;
import android.content.ComponentName;
@@ -107,7 +106,7 @@
}
public static Bundle checkUserRestrictions(String... keys) {
- final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys));
+ final Bundle expected = DpmTestUtils.newRestrictions(java.util.Objects.requireNonNull(keys));
final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
@Override
public boolean matches(Object item) {
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index a2376a6..604efc4 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -32,6 +32,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -64,7 +65,6 @@
import com.android.server.integrity.model.IntegrityCheckResult;
import com.android.server.testutils.TestUtils;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -75,9 +75,6 @@
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -86,7 +83,8 @@
/** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
@RunWith(AndroidJUnit4.class)
public class AppIntegrityManagerServiceImplTest {
- private static final String TEST_DIR = "AppIntegrityManagerServiceImplTest";
+ private static final String TEST_APP_PATH =
+ "/data/local/tmp/AppIntegrityManagerServiceTestApp.apk";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
private static final String VERSION = "version";
@@ -97,13 +95,19 @@
private static final String INSTALLER = TEST_FRAMEWORK_PACKAGE;
// These are obtained by running the test and checking logcat.
private static final String APP_CERT =
- "949ADC6CB92FF09E3784D6E9504F26F9BEAC06E60D881D55A6A81160F9CD6FD1";
+ "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
private static final String INSTALLER_CERT =
"301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
// We use SHA256 for package names longer than 32 characters.
private static final String INSTALLER_SHA256 =
"786933C28839603EB48C50B2A688DC6BE52C833627CB2731FF8466A2AE9F94CD";
+ private static final String PLAY_STORE_PKG = "com.android.vending";
+ private static final String ADB_INSTALLER = "adb";
+ private static final String PLAY_STORE_CERT =
+ "play_store_cert";
+ private static final String ADB_CERT = "";
+
@org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock PackageManagerInternal mPackageManagerInternal;
@@ -122,11 +126,7 @@
@Before
public void setup() throws Exception {
- mTestApk = File.createTempFile("TestApk", /* suffix= */ null);
- mTestApk.deleteOnExit();
- try (InputStream inputStream = mRealContext.getAssets().open(TEST_DIR + "/test.apk")) {
- Files.copy(inputStream, mTestApk.toPath(), StandardCopyOption.REPLACE_EXISTING);
- }
+ mTestApk = new File(TEST_APP_PATH);
mService =
new AppIntegrityManagerServiceImpl(
@@ -141,11 +141,7 @@
when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
- }
-
- @After
- public void tearDown() throws Exception {
- mTestApk.delete();
+ when(mIntegrityFileManager.initialized()).thenReturn(true);
}
// This is not a test of the class, but more of a safeguard that we don't block any install in
@@ -310,10 +306,10 @@
assertEquals(INSTALLER_CERT, appInstallMetadata.getInstallerCertificate());
assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode());
assertFalse(appInstallMetadata.isPreInstalled());
- // These are hardcoded in the test apk
+ // These are hardcoded in the test apk android manifest
assertEquals(2, allowedInstallers.size());
- assertEquals("cert_1", allowedInstallers.get("store_1"));
- assertEquals("cert_2", allowedInstallers.get("store_2"));
+ assertEquals(PLAY_STORE_CERT, allowedInstallers.get(PLAY_STORE_PKG));
+ assertEquals(ADB_CERT, allowedInstallers.get(ADB_INSTALLER));
}
@Test
@@ -356,6 +352,25 @@
1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
}
+ @Test
+ public void handleBroadcast_notInitialized() throws Exception {
+ when(mIntegrityFileManager.initialized()).thenReturn(false);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+ when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
+
+ verify(mPackageManagerInternal)
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ verify(mSpyPackageManager, never()).getPackageArchiveInfo(any(), anyInt());
+ }
+
private void whitelistUsAsRuleProvider() {
Resources mockResources = mock(Resources.class);
when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
new file mode 100644
index 0000000..63189e7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItems;
+import static org.junit.Assert.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
+import android.util.Slog;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.integrity.parser.RuleXmlParser;
+import com.android.server.integrity.serializer.RuleXmlSerializer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/** Unit test for {@link IntegrityFileManager} */
+@RunWith(AndroidJUnit4.class)
+public class IntegrityFileManagerTest {
+ private static final String TAG = "IntegrityFileManagerTest";
+
+ private static final String VERSION = "version";
+ private static final String RULE_PROVIDER = "rule_provider";
+
+ private File mTmpDir;
+
+ // under test
+ private IntegrityFileManager mIntegrityFileManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mTmpDir = Files.createTempDirectory("IntegrityFileManagerTest").toFile();
+ Slog.i(TAG, "Using temp directory " + mTmpDir);
+
+ // Use Xml Parser/Serializer to help with debugging since we can just print the file.
+ mIntegrityFileManager =
+ new IntegrityFileManager(
+ new RuleXmlParser(), new RuleXmlSerializer(), mTmpDir);
+ Files.walk(mTmpDir.toPath())
+ .forEach(
+ path -> {
+ Slog.i(TAG, "before " + path);
+ });
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Files.walk(mTmpDir.toPath())
+ .forEach(
+ path -> {
+ Slog.i(TAG, "after " + path);
+ });
+ // Sorting paths in reverse order guarantees that we delete inside files before deleting
+ // directory.
+ Files.walk(mTmpDir.toPath())
+ .sorted(Comparator.reverseOrder())
+ .map(Path::toFile)
+ .forEach(File::delete);
+ }
+
+ @Test
+ public void testGetMetadata() throws Exception {
+ assertNull(mIntegrityFileManager.readMetadata());
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+
+ assertNotNull(mIntegrityFileManager.readMetadata());
+ assertEquals(VERSION, mIntegrityFileManager.readMetadata().getVersion());
+ assertEquals(RULE_PROVIDER, mIntegrityFileManager.readMetadata().getRuleProvider());
+ }
+
+ @Test
+ public void testGetRules() throws Exception {
+ String packageName = "package";
+ String packageCert = "cert";
+ int version = 123;
+ Rule packageNameRule =
+ new Rule(
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ Rule.DENY);
+ Rule packageCertRule =
+ new Rule(
+ new StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ packageCert,
+ /* isHashedValue= */ false),
+ Rule.DENY);
+ Rule versionCodeRule =
+ new Rule(
+ new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
+ Rule.DENY);
+ Rule randomRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.OR,
+ Arrays.asList(
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "abc",
+ /* isHashedValue= */ false),
+ new IntAtomicFormula(
+ AtomicFormula.VERSION_CODE,
+ AtomicFormula.LE,
+ version))),
+ Rule.DENY);
+ // We will test the specifics of indexing in other classes. Here, we just require that all
+ // rules that are related to the given AppInstallMetadata are returned and do not assert
+ // anything on other rules.
+ List<Rule> rules =
+ Arrays.asList(packageNameRule, packageCertRule, versionCodeRule, randomRule);
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
+
+ AppInstallMetadata appInstallMetadata = new AppInstallMetadata.Builder()
+ .setPackageName(packageName)
+ .setAppCertificate(packageCert)
+ .setVersionCode(version)
+ .setInstallerName("abc")
+ .setInstallerCertificate("abc")
+ .setIsPreInstalled(true)
+ .build();
+ List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
+
+ assertThat(rulesFetched, hasItems(
+ equalTo(packageNameRule),
+ equalTo(packageCertRule),
+ equalTo(versionCodeRule)
+ ));
+ }
+
+ @Test
+ public void testIsInitialized() throws Exception {
+ assertFalse(mIntegrityFileManager.initialized());
+ mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+ assertTrue(mIntegrityFileManager.initialized());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
index 94e11c6..55fada4 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
@@ -38,8 +38,10 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
/** Unit tests for {@link RuleIndexingDetailsIdentifier}. */
@RunWith(JUnit4.class)
@@ -138,14 +140,16 @@
List<Rule> ruleList = new ArrayList();
ruleList.add(RULE_WITH_PACKAGE_NAME);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
// Verify the resulting map content.
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
assertThat(result.get(NOT_INDEXED)).isEmpty();
assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
- assertThat(result.get(PACKAGE_NAME_INDEXED)).containsExactly(RULE_WITH_PACKAGE_NAME);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly(SAMPLE_PACKAGE_NAME);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get(SAMPLE_PACKAGE_NAME))
+ .containsExactly(RULE_WITH_PACKAGE_NAME);
}
@Test
@@ -153,13 +157,16 @@
List<Rule> ruleList = new ArrayList();
ruleList.add(RULE_WITH_APP_CERTIFICATE);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
assertThat(result.get(NOT_INDEXED)).isEmpty();
assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
- assertThat(result.get(APP_CERTIFICATE_INDEXED)).containsExactly(RULE_WITH_APP_CERTIFICATE);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet())
+ .containsExactly(SAMPLE_APP_CERTIFICATE);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get(SAMPLE_APP_CERTIFICATE))
+ .containsExactly(RULE_WITH_APP_CERTIFICATE);
}
@Test
@@ -167,13 +174,14 @@
List<Rule> ruleList = new ArrayList();
ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
- assertThat(result.get(NOT_INDEXED)).containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS);
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
+ .containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS);
}
@Test
@@ -181,13 +189,14 @@
List<Rule> ruleList = new ArrayList();
ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
- assertThat(result.get(NOT_INDEXED)).containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS);
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
+ .containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS);
}
@Test
@@ -206,13 +215,13 @@
List<Rule> ruleList = new ArrayList();
ruleList.add(negatedRule);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
- assertThat(result.get(NOT_INDEXED)).containsExactly(negatedRule);
+ assertThat(result.get(NOT_INDEXED).get("N/A")).containsExactly(negatedRule);
}
@Test
@@ -234,22 +243,36 @@
ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
- Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+ Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
assertThat(result.keySet())
.containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
// We check asserts this way to ensure ordering based on package name.
- assertThat(result.get(PACKAGE_NAME_INDEXED).get(0)).isEqualTo(packageNameRuleA);
- assertThat(result.get(PACKAGE_NAME_INDEXED).get(1)).isEqualTo(packageNameRuleB);
- assertThat(result.get(PACKAGE_NAME_INDEXED).get(2)).isEqualTo(packageNameRuleC);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly("aaa", "bbb", "ccc");
+ Iterator<String> keySetIterator = result.get(PACKAGE_NAME_INDEXED).keySet().iterator();
+ assertThat(keySetIterator.next()).isEqualTo("aaa");
+ assertThat(keySetIterator.next()).isEqualTo("bbb");
+ assertThat(keySetIterator.next()).isEqualTo("ccc");
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("aaa")).containsExactly(packageNameRuleA);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("bbb")).containsExactly(packageNameRuleB);
+ assertThat(result.get(PACKAGE_NAME_INDEXED).get("ccc")).containsExactly(packageNameRuleC);
// We check asserts this way to ensure ordering based on app certificate.
- assertThat(result.get(APP_CERTIFICATE_INDEXED).get(0)).isEqualTo(certificateRule1);
- assertThat(result.get(APP_CERTIFICATE_INDEXED).get(1)).isEqualTo(certificateRule2);
- assertThat(result.get(APP_CERTIFICATE_INDEXED).get(2)).isEqualTo(certificateRule3);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet()).containsExactly("cert1", "cert2",
+ "cert3");
+ keySetIterator = result.get(APP_CERTIFICATE_INDEXED).keySet().iterator();
+ assertThat(keySetIterator.next()).isEqualTo("cert1");
+ assertThat(keySetIterator.next()).isEqualTo("cert2");
+ assertThat(keySetIterator.next()).isEqualTo("cert3");
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert1")).containsExactly(
+ certificateRule1);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert2")).containsExactly(
+ certificateRule2);
+ assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert3")).containsExactly(
+ certificateRule3);
- assertThat(result.get(NOT_INDEXED))
+ assertThat(result.get(NOT_INDEXED).get("N/A"))
.containsExactly(
RULE_WITH_INSTALLER_RESTRICTIONS,
RULE_WITH_NONSTRING_RESTRICTIONS);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f9fc3a1..41416f1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -88,7 +88,6 @@
import android.util.Log;
import android.util.Pair;
-import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
@@ -114,6 +113,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
@@ -1241,7 +1241,7 @@
protected void setCaller(String packageName, int userId) {
mInjectedClientPackage = packageName;
mInjectedCallingUid =
- Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
+ Objects.requireNonNull(getInjectedPackageInfo(packageName, userId, false),
"Unknown package").applicationInfo.uid;
// Set up LauncherApps for this caller.
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
index aec489c..757a884 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java
@@ -53,8 +53,7 @@
if (a == null || b == null) {
return a == b;
}
- return a.getLongVersionCode() == b.getLongVersionCode()
- && Objects.equals(a.getPackageName(), b.getPackageName());
+ return a.equals(b);
}
@Override
@@ -298,15 +297,8 @@
private void assertPackageRollbacksAreEquivalent(PackageRollbackInfo b, PackageRollbackInfo a) {
assertThat(b.getPackageName()).isEqualTo(a.getPackageName());
- assertThat(b.getVersionRolledBackFrom().getLongVersionCode())
- .isEqualTo(a.getVersionRolledBackFrom().getLongVersionCode());
- assertThat(b.getVersionRolledBackFrom().getPackageName())
- .isEqualTo(a.getVersionRolledBackFrom().getPackageName());
-
- assertThat(b.getVersionRolledBackTo().getLongVersionCode())
- .isEqualTo(a.getVersionRolledBackTo().getLongVersionCode());
- assertThat(b.getVersionRolledBackTo().getPackageName())
- .isEqualTo(a.getVersionRolledBackTo().getPackageName());
+ assertThat(b.getVersionRolledBackFrom()).isEqualTo(a.getVersionRolledBackFrom());
+ assertThat(b.getVersionRolledBackTo()).isEqualTo(a.getVersionRolledBackTo());
assertThat(b.getPendingBackups().toArray()).isEqualTo(a.getPendingBackups().toArray());
diff --git a/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp
new file mode 100644
index 0000000..9aaa37d
--- /dev/null
+++ b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp
@@ -0,0 +1,21 @@
+// Copyright (C) 2017 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.
+
+android_test_helper_app {
+ name: "AppIntegrityManagerServiceTestApp",
+
+ test_suites: ["device-tests"],
+
+ certificate: "platform",
+}
diff --git a/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..f5dbf43
--- /dev/null
+++ b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.appintegritymanager.test.app"
+ android:versionCode="5000">
+
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="28" />
+
+ <application android:hasCode="false">
+ <meta-data android:name="allowed-installers" android:value="com.android.vending|play_store_cert,adb|"/>
+ </application>
+</manifest>
+
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index c24ce2b..a5157fe9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -236,7 +236,7 @@
// Overlay must be for a different user to prevent recognizing a matching top activity
final ActivityRecord taskOverlay = new ActivityBuilder(mService).setTask(task)
.setUid(UserHandle.PER_USER_RANGE * 2).build();
- taskOverlay.mTaskOverlay = true;
+ taskOverlay.setTaskOverlay(true);
final RootWindowContainer.FindTaskResult result =
new RootWindowContainer.FindTaskResult();
@@ -574,6 +574,27 @@
}
@Test
+ public void testShouldBeVisible_FullscreenBehindTranslucentInHomeStack() {
+ final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
+
+ final ActivityRecord firstActivity = new ActivityBuilder(mService)
+ .setStack(homeStack)
+ .setCreateTask(true)
+ .build();
+ final Task task = firstActivity.getTask();
+ final ActivityRecord secondActivity = new ActivityBuilder(mService)
+ .setTask(task)
+ .build();
+
+ doReturn(false).when(secondActivity).occludesParent();
+ homeStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */);
+
+ assertTrue(firstActivity.shouldBeVisible());
+ }
+
+ @Test
public void testMoveHomeStackBehindBottomMostVisibleStack_NoMoveHomeBehindFullscreen() {
mDefaultDisplay.removeStack(mStack);
@@ -865,7 +886,7 @@
.setComponent(new ComponentName("package.overlay", ".OverlayActivity")).build();
// If the task only remains overlay activity, the task should also be removed.
// See {@link ActivityStack#removeFromHistory}.
- overlayActivity.mTaskOverlay = true;
+ overlayActivity.setTaskOverlay(true);
// The activity without an app means it will be removed immediately.
// See {@link ActivityStack#destroyActivityLocked}.
@@ -893,7 +914,7 @@
// Making the first activity a task overlay means it will be removed from the task's
// activities as well once second activity is removed as handleAppDied processes the
// activity list in reverse.
- firstActivity.mTaskOverlay = true;
+ firstActivity.setTaskOverlay(true);
firstActivity.app = null;
// second activity will be immediately removed as it has no state.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index fc94c5e..8c2b293 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -61,7 +61,7 @@
public void setUpOnDisplay(DisplayContent dc) {
mActivity = createTestActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mTask = mActivity.getTask();
- mStack = mTask.getTaskStack();
+ mStack = mTask.getStack();
// Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 0758eeb..73dd2df 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -126,7 +126,7 @@
waitUntilHandlersIdle();
exitingApp.mIsExiting = true;
- exitingApp.getTask().getTaskStack().mExitingActivities.add(exitingApp);
+ exitingApp.getTask().getStack().mExitingActivities.add(exitingApp);
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 31b658a..cf1f0a8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -424,7 +424,7 @@
void saveTask(Task task) {
final int userId = task.mUserId;
final ComponentName realActivity = task.realActivity;
- mTmpParams.mPreferredDisplayId = task.getStack().mDisplayId;
+ mTmpParams.mPreferredDisplayId = task.getDisplayId();
mTmpParams.mWindowingMode = task.getWindowingMode();
if (task.mLastNonFullscreenBounds != null) {
mTmpParams.mBounds.set(task.mLastNonFullscreenBounds);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 55a139a..79f808e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -421,6 +421,7 @@
@Test
public void testUsersTasks() {
mRecentTasks.setOnlyTestVisibleRange();
+ mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_0_ID);
// Setup some tasks for the users
mTaskPersister.mUserTaskIdsOverride = new SparseBooleanArray();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 9f092835..04d79ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -857,7 +857,7 @@
// Assert that the stack is returned as expected.
assertNotNull(result);
assertEquals("The display ID of the stack should same as secondary display ",
- secondaryDisplay.mDisplayId, result.mDisplayId);
+ secondaryDisplay.mDisplayId, result.getDisplayId());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index f90eca3..e27c724 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -433,7 +433,7 @@
doReturn(aos).when(this).getAppOpsService();
// Make sure permission checks aren't overridden.
doReturn(AppOpsManager.MODE_DEFAULT).when(aos).noteOperation(anyInt(), anyInt(),
- anyString(), nullable(String.class));
+ anyString(), nullable(String.class), anyBoolean(), nullable(String.class));
// UserManagerService
final UserManagerService ums = mock(UserManagerService.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 9f2bfa7..9562fa4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -345,6 +345,7 @@
spyOn(parentWindowContainer);
parentWindowContainer.setBounds(fullScreenBounds);
doReturn(parentWindowContainer).when(task).getParent();
+ doReturn(stack).when(task).getStack();
doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
// Setting app to fixed portrait fits within parent, but Task shouldn't adjust the
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 6c3410a..b4f5751 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -110,12 +110,12 @@
public void testStackRemoveImmediately() {
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- assertEquals(stack, task.getTaskStack());
+ assertEquals(stack, task.getStack());
// Remove stack and check if its child is also removed.
stack.removeImmediately();
assertNull(stack.getDisplayContent());
- assertNull(task.getTaskStack());
+ assertNull(task.getStack());
}
@Test
@@ -131,7 +131,7 @@
assertEquals(0, stack.getChildCount());
assertNull(stack.getDisplayContent());
assertNull(task.getDisplayContent());
- assertNull(task.getTaskStack());
+ assertNull(task.getStack());
}
@Test
diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
new file mode 100644
index 0000000..b75510b
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.startop.iorap;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.server.wm.ActivityMetricsLaunchObserver;
+
+/**
+ * A validator to check the correctness of event sequence during app startup.
+ *
+ * <p> A valid state transition of event sequence is shown as the following:
+ *
+ * <pre>
+ *
+ * +--------------------+
+ * | |
+ * | INIT |
+ * | |
+ * +--------------------+
+ * |
+ * |
+ * ↓
+ * +--------------------+
+ * | |
+ * +-------------------| INTENT_STARTED | ←--------------------------------+
+ * | | | |
+ * | +--------------------+ |
+ * | | |
+ * | | |
+ * ↓ ↓ |
+ * +--------------------+ +--------------------+ |
+ * | | | | |
+ * | INTENT_FAILED | | ACTIVITY_LAUNCHED |------------------+ |
+ * | | | | | |
+ * +--------------------+ +--------------------+ | |
+ * | | | |
+ * | ↓ ↓ |
+ * | +--------------------+ +--------------------+ |
+ * | | | | | |
+ * +------------------ | ACTIVITY_FINISHED | | ACTIVITY_CANCELLED | |
+ * | | | | | |
+ * | +--------------------+ +--------------------+ |
+ * | | | |
+ * | | | |
+ * | ↓ | |
+ * | +--------------------+ | |
+ * | | | | |
+ * | | REPORT_FULLY_DRAWN | | |
+ * | | | | |
+ * | +--------------------+ | |
+ * | | | |
+ * | | | |
+ * | ↓ | |
+ * | +--------------------+ | |
+ * | | | | |
+ * +-----------------→ | END |←-----------------+ |
+ * | | |
+ * +--------------------+ |
+ * | |
+ * | |
+ * | |
+ * +---------------------------------------------
+ *
+ * <p> END is not a real state in implementation. All states that points to END directly
+ * could transition to INTENT_STARTED.
+ *
+ * <p> If any bad transition happened, the state becomse UNKNOWN. The UNKNOWN state
+ * could be * accumulated, because during the UNKNOWN state more IntentStarted may
+ * be triggered. To recover from UNKNOWN to INIT, all the accumualted IntentStarted
+ * should termniate.
+ *
+ * <p> During UNKNOWN state, each IntentStarted increases the accumulation, and any of
+ * IntentFailed, ActivityLaunchCancelled and ActivityFinished decreases the accumulation.
+ * ReportFullyDrawn doesn't impact the accumulation.
+ */
+public class EventSequenceValidator implements ActivityMetricsLaunchObserver {
+ static final String TAG = "EventSequenceValidator";
+
+ private State state = State.INIT;
+ private long accIntentStartedEvents = 0;
+
+ @Override
+ public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "IntentStarted during UNKNOWN." + intent);
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ if (state != State.INIT &&
+ state != State.INTENT_FAILED &&
+ state != State.ACTIVITY_CANCELLED &&
+ state != State.ACTIVITY_FINISHED &&
+ state != State.REPORT_FULLY_DRAWN) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.INTENT_STARTED));
+ incAccIntentStartedEvents();
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_STARTED));
+ state = State.INTENT_STARTED;
+ }
+
+ @Override
+ public void onIntentFailed() {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "IntentFailed during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+ if (state != State.INTENT_STARTED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.INTENT_FAILED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_FAILED));
+ state = State.INTENT_FAILED;
+ }
+
+ @Override
+ public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
+ @Temperature int temperature) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunched during UNKNOWN.");
+ return;
+ }
+ if (state != State.INTENT_STARTED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+ state = State.ACTIVITY_LAUNCHED;
+ }
+
+ @Override
+ public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunchCancelled during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+ if (state != State.ACTIVITY_LAUNCHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+ state = State.ACTIVITY_CANCELLED;
+ }
+
+ @Override
+ public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
+ long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onActivityLaunchFinished during UNKNOWN.");
+ decAccIntentStartedEvents();
+ return;
+ }
+
+ if (state != State.ACTIVITY_LAUNCHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.ACTIVITY_FINISHED));
+ incAccIntentStartedEvents();
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_FINISHED));
+ state = State.ACTIVITY_FINISHED;
+ }
+
+ @Override
+ public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
+ long timestampNs) {
+ if (state == State.UNKNOWN) {
+ Log.e(TAG, "onReportFullyDrawn during UNKNOWN.");
+ return;
+ }
+ if (state == State.INIT) {
+ return;
+ }
+
+ if (state != State.ACTIVITY_FINISHED) {
+ Log.e(TAG,
+ String.format("Cannot transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+ return;
+ }
+
+ Log.i(TAG, String.format("Transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+ state = State.REPORT_FULLY_DRAWN;
+ }
+
+ enum State {
+ INIT,
+ INTENT_STARTED,
+ INTENT_FAILED,
+ ACTIVITY_LAUNCHED,
+ ACTIVITY_CANCELLED,
+ ACTIVITY_FINISHED,
+ REPORT_FULLY_DRAWN,
+ UNKNOWN,
+ }
+
+ private void incAccIntentStartedEvents() {
+ if (accIntentStartedEvents < 0) {
+ throw new AssertionError(
+ String.format("The number of unknows cannot be negative"));
+ }
+ if (accIntentStartedEvents == 0) {
+ state = State.UNKNOWN;
+ }
+ ++accIntentStartedEvents;
+ Log.i(TAG,
+ String.format("inc AccIntentStartedEvents to %d", accIntentStartedEvents));
+ }
+
+ private void decAccIntentStartedEvents() {
+ if (accIntentStartedEvents <= 0) {
+ throw new AssertionError(
+ String.format("The number of unknows cannot be negative"));
+ }
+ if(accIntentStartedEvents == 1) {
+ state = State.INIT;
+ }
+ --accIntentStartedEvents;
+ Log.i(TAG,
+ String.format("dec AccIntentStartedEvents to %d", accIntentStartedEvents));
+ }
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index f753548..badff7b 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -283,6 +283,7 @@
}
private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
+ private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
private boolean mRegisteredListeners = false;
private void registerInProcessListenersLocked() {
@@ -303,6 +304,7 @@
ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
provideLaunchObserverRegistry();
launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
+ launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
mRegisteredListeners = true;
}
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 0659665..9e6dfef 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -98,7 +98,13 @@
TelephonyManager.NETWORK_TYPE_GSM,
TelephonyManager.NETWORK_TYPE_TD_SCDMA,
TelephonyManager.NETWORK_TYPE_IWLAN,
- TelephonyManager.NETWORK_TYPE_LTE_CA,
+
+ //TODO: In order for @SystemApi methods to use this class, there cannot be any
+ // public hidden members. This network type is marked as hidden because it is not a
+ // true network type and we are looking to remove it completely from the available list
+ // of network types.
+ //TelephonyManager.NETWORK_TYPE_LTE_CA,
+
TelephonyManager.NETWORK_TYPE_NR,
})
@Retention(RetentionPolicy.SOURCE)
@@ -590,4 +596,17 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ImsAudioCodec {
}
+
+ /**
+ * UICC SIM Application Types
+ */
+ @IntDef(prefix = { "APPTYPE_" }, value = {
+ TelephonyManager.APPTYPE_SIM,
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.APPTYPE_RUIM,
+ TelephonyManager.APPTYPE_CSIM,
+ TelephonyManager.APPTYPE_ISIM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UiccAppType{}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ab51d8a..599cd9f 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -379,15 +379,15 @@
/**
* Create a new ServiceState from a intent notifier Bundle
*
- * This method is used by PhoneStateIntentReceiver, CellBroadcastReceiver, and maybe by
- * external applications.
+ * This method is used to get ServiceState object from extras upon receiving
+ * {@link Intent#ACTION_SERVICE_STATE}.
*
* @param m Bundle from intent notifier
* @return newly created ServiceState
* @hide
*/
+ @SystemApi
@NonNull
- @UnsupportedAppUsage
public static ServiceState newFromBundle(@NonNull Bundle m) {
ServiceState ret;
ret = new ServiceState();
@@ -1281,11 +1281,15 @@
/**
* Set intent notifier Bundle based on service state.
*
+ * Put ServiceState object and its fields into bundle which is used by TelephonyRegistry
+ * to broadcast {@link Intent#ACTION_SERVICE_STATE}.
+ *
* @param m intent notifier Bundle
* @hide
+ *
*/
- @UnsupportedAppUsage
- public void fillInNotifierBundle(Bundle m) {
+ @SystemApi
+ public void fillInNotifierBundle(@NonNull Bundle m) {
m.putParcelable(Intent.EXTRA_SERVICE_STATE, this);
// serviceState already consists of below entries.
// for backward compatibility, we continue fill in below entries.
@@ -1950,9 +1954,18 @@
* Returns a copy of self with location-identifying information removed.
* Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
* is true, clears other info as well.
+ *
+ * @param removeCoarseLocation Whether to also remove coarse location information.
+ * if false, it only clears fine location information such as
+ * NetworkRegistrationInfo's CellIdentity fields; If true, it will
+ * also remove other location information such as operator's MCC
+ * and MNC.
+ * @return the copied ServiceState with location info sanitized.
* @hide
*/
- public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+ @SystemApi
+ @NonNull
+ public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
ServiceState state = new ServiceState(this);
synchronized (state.mNetworkRegistrationInfos) {
List<NetworkRegistrationInfo> networkRegistrationInfos =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 365ab22..20c9f6c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -17,6 +17,8 @@
package android.telephony;
import static android.content.Context.TELECOM_SERVICE;
+import static android.provider.Telephony.Carriers.DPC_URI;
+import static android.provider.Telephony.Carriers.INVALID_APN_ID;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -44,6 +46,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.Uri;
@@ -73,7 +76,9 @@
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.UiccAppType;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting.MvnoType;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
@@ -6781,19 +6786,6 @@
}
}
- /**
- * UICC SIM Application Types
- * @hide
- */
- @IntDef(prefix = { "APPTYPE_" }, value = {
- APPTYPE_SIM,
- APPTYPE_USIM,
- APPTYPE_RUIM,
- APPTYPE_CSIM,
- APPTYPE_ISIM
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface UiccAppType{}
/** UICC application type is SIM */
public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
/** UICC application type is USIM */
@@ -8213,9 +8205,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPin(pin);
+ return telephony.supplyPinForSubscriber(getSubId(), pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPin", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPinForSubscriber", e);
}
return false;
}
@@ -8227,9 +8219,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPuk(puk, pin);
+ return telephony.supplyPukForSubscriber(getSubId(), puk, pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPuk", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPukForSubscriber", e);
}
return false;
}
@@ -8241,9 +8233,9 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPinReportResult(pin);
+ return telephony.supplyPinReportResultForSubscriber(getSubId(), pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPinReportResult", e);
+ Log.e(TAG, "Error calling ITelephony#supplyPinReportResultForSubscriber", e);
}
return new int[0];
}
@@ -8255,7 +8247,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.supplyPukReportResult(puk, pin);
+ return telephony.supplyPukReportResultForSubscriber(getSubId(), puk, pin);
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#]", e);
}
@@ -11872,6 +11864,88 @@
}
/**
+ * Returns a list of APNs set as overrides by the device policy manager via
+ * {@link #addDevicePolicyOverrideApn}.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @return {@link List} of APNs that have been set as overrides.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public @NonNull List<ApnSetting> getDevicePolicyOverrideApns(@NonNull Context context) {
+ try (Cursor cursor = context.getContentResolver().query(DPC_URI, null, null, null, null)) {
+ if (cursor == null) {
+ return Collections.emptyList();
+ }
+ List<ApnSetting> apnList = new ArrayList<ApnSetting>();
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ ApnSetting apn = ApnSetting.makeApnSetting(cursor);
+ apnList.add(apn);
+ }
+ return apnList;
+ }
+ }
+
+ /**
+ * Used by the device policy manager to add a new override APN.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @param apnSetting The {@link ApnSetting} describing the new APN.
+ * @return An integer, corresponding to a primary key in a database, that allows the caller to
+ * modify the APN in the future via {@link #modifyDevicePolicyOverrideApn}, or
+ * {@link android.provider.Telephony.Carriers.INVALID_APN_ID} if the override operation
+ * failed.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public int addDevicePolicyOverrideApn(@NonNull Context context,
+ @NonNull ApnSetting apnSetting) {
+ Uri resultUri = context.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
+
+ int resultId = INVALID_APN_ID;
+ if (resultUri != null) {
+ try {
+ resultId = Integer.parseInt(resultUri.getLastPathSegment());
+ } catch (NumberFormatException e) {
+ Rlog.e(TAG, "Failed to parse inserted override APN id: "
+ + resultUri.getLastPathSegment());
+ }
+ }
+ return resultId;
+ }
+
+ /**
+ * Used by the device policy manager to modify an override APN.
+ * This method must only be called from the system or phone processes.
+ *
+ * @param context Context to use.
+ * @param apnId The integer key of the APN to modify, as returned by
+ * {@link #addDevicePolicyOverrideApn}
+ * @param apnSetting The {@link ApnSetting} describing the updated APN.
+ * @return {@code true} if successful, {@code false} otherwise.
+ * @throws {@link SecurityException} if the caller is not the system or phone process.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ // TODO: add new permission tag indicating that this is system-only.
+ public boolean modifyDevicePolicyOverrideApn(@NonNull Context context, int apnId,
+ @NonNull ApnSetting apnSetting) {
+ return context.getContentResolver().update(
+ Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+ apnSetting.toContentValues(), null, null) > 0;
+ }
+
+ /**
* Return whether data is enabled for certain APN type. This will tell if framework will accept
* corresponding network requests on a subId.
*
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 57fda9b1..9d721fc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -117,13 +117,6 @@
*/
boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
- /**
- * Supply a pin to unlock the SIM. Blocks until a result is determined.
- * @param pin The pin to check.
- * @return whether the operation was a success.
- */
- @UnsupportedAppUsage
- boolean supplyPin(String pin);
/**
* Supply a pin to unlock the SIM for particular subId.
@@ -139,15 +132,6 @@
* Blocks until a result is determined.
* @param puk The puk to check.
* pin The new pin to be set in SIM
- * @return whether the operation was a success.
- */
- boolean supplyPuk(String puk, String pin);
-
- /**
- * Supply puk to unlock the SIM and set SIM pin to new pin.
- * Blocks until a result is determined.
- * @param puk The puk to check.
- * pin The new pin to be set in SIM
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
@@ -160,15 +144,6 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPinReportResult(String pin);
-
- /**
- * Supply a pin to unlock the SIM. Blocks until a result is determined.
- * Returns a specific success/error code.
- * @param pin The pin to check.
- * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
- * retValue[1] = number of attempts remaining if known otherwise -1
- */
int[] supplyPinReportResultForSubscriber(int subId, String pin);
/**
@@ -180,17 +155,6 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPukReportResult(String puk, String pin);
-
- /**
- * Supply puk to unlock the SIM and set SIM pin to new pin.
- * Blocks until a result is determined.
- * Returns a specific success/error code
- * @param puk The puk to check
- * pin The pin to check.
- * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
- * retValue[1] = number of attempts remaining if known otherwise -1
- */
int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin);
/**
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index daa85bd..f6699fa 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -31,6 +31,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.UserManager;
@@ -1122,4 +1123,39 @@
InstallUtils.dropShellPermissionIdentity();
}
}
+
+ @Test
+ public void testRollbackDataPolicy() throws Exception {
+ try {
+ InstallUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS);
+
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ // Write user data version = 1
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ Install a2 = Install.single(TestApp.A2)
+ .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+ Install b2 = Install.single(TestApp.B2)
+ .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+ Install.multi(a2, b2).setEnableRollback().commit();
+ // Write user data version = 2
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+ RollbackUtils.rollback(info.getRollbackId());
+ // Read user data version from userdata.txt
+ // A's user data version is -1 for user data is wiped.
+ // B's user data version is 1 as rollback committed.
+ assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+ assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+ } finally {
+ InstallUtils.dropShellPermissionIdentity();
+ }
+ }
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index bb3906d..40169b8 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -384,6 +384,44 @@
RollbackUtils.getRollbackManager().expireRollbackForPackage(getModuleMetadataPackageName());
}
+ @Test
+ public void testRollbackDataPolicy_Phase1() throws Exception {
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ // Write user data version = 1
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ Install a2 = Install.single(TestApp.A2).setStaged()
+ .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+ Install b2 = Install.single(TestApp.B2).setStaged()
+ .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+ Install.multi(a2, b2).setEnableRollback().setStaged().commit();
+ }
+
+ @Test
+ public void testRollbackDataPolicy_Phase2() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+ // Write user data version = 2
+ InstallUtils.processUserData(TestApp.A);
+ InstallUtils.processUserData(TestApp.B);
+
+ RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+ RollbackUtils.rollback(info.getRollbackId());
+ }
+
+ @Test
+ public void testRollbackDataPolicy_Phase3() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
+ // Read user data version from userdata.txt
+ // A's user data version is -1 for user data is wiped.
+ // B's user data version is 1 as rollback committed.
+ assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+ assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+ }
+
private static void runShellCommand(String cmd) {
ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand(cmd);
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 8ab4c4c..4644d8a 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -192,6 +192,15 @@
}
}
+ @Test
+ public void testRollbackDataPolicy() throws Exception {
+ runPhase("testRollbackDataPolicy_Phase1");
+ getDevice().reboot();
+ runPhase("testRollbackDataPolicy_Phase2");
+ getDevice().reboot();
+ runPhase("testRollbackDataPolicy_Phase3");
+ }
+
private void crashProcess(String processName, int numberOfCrashes) throws Exception {
String pid = "";
String lastPid = "invalid";
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index b725920..27960c8 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -365,6 +365,8 @@
});
manifest_action["instrumentation"]["meta-data"] = meta_data_action;
+ manifest_action["feature"];
+ manifest_action["feature"]["inherit-from"];
manifest_action["original-package"];
manifest_action["overlay"];
manifest_action["protected-broadcast"];
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 15c3278..d3958a6 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -25,6 +25,8 @@
"java_writer.cpp",
"java_writer_q.cpp",
"main.cpp",
+ "native_writer.cpp",
+ "native_writer_q.cpp",
"utils.cpp",
],
cflags: [
@@ -121,17 +123,5 @@
"libcutils",
],
static_libs: ["libstatssocket"],
- target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: [
- "libutils",
- ],
- },
- },
}
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index fa55601..0b82a3d 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -405,9 +405,9 @@
atomDecl.whitelisted = true;
}
- if (atomField->options().HasExtension(os::statsd::log_from_module)) {
+ if (atomField->options().HasExtension(os::statsd::module)) {
atomDecl.hasModule = true;
- atomDecl.moduleName = atomField->options().GetExtension(os::statsd::log_from_module);
+ atomDecl.moduleName = atomField->options().GetExtension(os::statsd::module);
}
vector<java_type_t> signature;
diff --git a/tools/stats_log_api_gen/atoms_info_writer.h b/tools/stats_log_api_gen/atoms_info_writer.h
index bc67782..12ac862 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.h
+++ b/tools/stats_log_api_gen/atoms_info_writer.h
@@ -27,8 +27,7 @@
using namespace std;
int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
- const string& importHeader, const string& statslogHeader
-);
+ const string& importHeader, const string& statslogHeader);
int write_atoms_info_header(FILE* out, const Atoms& atoms, const string& namespaceStr);
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 712b48e..7f0872c 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -48,7 +48,8 @@
FILE* out,
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
const AtomDecl &attributionDecl,
- const string& moduleName
+ const string& moduleName,
+ const bool supportQ
) {
for (auto signature_to_modules_it = signatures_to_modules.begin();
signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
@@ -82,8 +83,10 @@
// Print method body.
string indent("");
- if (DEFAULT_MODULE_NAME != moduleName) {
- fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
+ if (supportQ) {
+ // TODO(b/146235828): Use just SDK_INT check once it is incremented from Q.
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ||\n");
+ fprintf(out, " Build.VERSION.CODENAME.equals(\"R\")) {\n");
indent = " ";
}
@@ -193,7 +196,7 @@
fprintf(out, "%s StatsLog.write(builder.build());\n", indent.c_str());
// Add support for writing using Q schema if this is not the default module.
- if (DEFAULT_MODULE_NAME != moduleName) {
+ if (supportQ) {
fprintf(out, " } else {\n");
fprintf(out, " QLogger.write(code");
argIndex = 1;
@@ -225,15 +228,17 @@
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
const string& moduleName, const string& javaClass,
- const string& javaPackage) {
+ const string& javaPackage, const bool supportQ) {
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
fprintf(out, "package %s;\n", javaPackage.c_str());
fprintf(out, "\n");
fprintf(out, "\n");
- fprintf(out, "import android.os.Build;\n");
- fprintf(out, "import android.os.SystemClock;\n");
+ if (supportQ) {
+ fprintf(out, "import android.os.Build;\n");
+ fprintf(out, "import android.os.SystemClock;\n");
+ }
if (DEFAULT_MODULE_NAME == moduleName) {
// Mainline modules don't use WorkSource logging.
@@ -271,12 +276,15 @@
// Print write methods.
fprintf(out, " // Write methods\n");
- errors += write_java_methods(out, atoms.signatures_to_modules, attributionDecl, moduleName);
+ errors += write_java_methods(
+ out, atoms.signatures_to_modules, attributionDecl, moduleName, supportQ);
errors += write_java_non_chained_methods(
out, atoms.non_chained_signatures_to_modules, moduleName);
if (DEFAULT_MODULE_NAME == moduleName) {
errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
- } else {
+ }
+
+ if (supportQ) {
errors += write_java_q_logger_class(
out, atoms.signatures_to_modules, attributionDecl, moduleName);
}
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
index 031266b..9324b23 100644
--- a/tools/stats_log_api_gen/java_writer.h
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -32,8 +32,7 @@
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
const string& moduleName, const string& javaClass,
- const string& javaPackage
-);
+ const string& javaPackage, const bool supportQ);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index c8f4ccf..96ac745 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -37,22 +37,20 @@
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
const AtomDecl &attributionDecl,
const string& moduleName,
- const string& indent
-);
+ const string& indent);
void write_java_helpers_for_q_schema_methods(
FILE * out,
const AtomDecl &attributionDecl,
const int requiredHelpers,
- const string& indent
-);
+ const string& indent);
#if defined(STATS_SCHEMA_LEGACY)
int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& javaClass,
- const string& javaPackage);
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
+ const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass,
+ const string& javaPackage);
#endif
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index ad171da..00a3704 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -6,6 +6,7 @@
#include "java_writer.h"
#endif
#include "java_writer_q.h"
+#include "native_writer.h"
#include "utils.h"
#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
@@ -27,496 +28,6 @@
using android::os::statsd::Atom;
-static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace,
- const string& importHeader) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
-
- fprintf(out, "#include <mutex>\n");
- fprintf(out, "#include <chrono>\n");
- fprintf(out, "#include <thread>\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "#include <cutils/properties.h>\n");
- fprintf(out, "#endif\n");
- fprintf(out, "#include <stats_event_list.h>\n");
- fprintf(out, "#include <log/log.h>\n");
- fprintf(out, "#include <%s>\n", importHeader.c_str());
- fprintf(out, "#include <utils/SystemClock.h>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "// the single event tag id for all stats logs\n");
- fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
- fprintf(out, "#ifdef __ANDROID__\n");
- fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
- fprintf(out, "#else\n");
- fprintf(out, "const static bool kStatsdEnabled = false;\n");
- fprintf(out, "#endif\n");
-
- fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
- fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
- fprintf(out, "static std::mutex mLogdRetryMutex;\n");
-
- // Print write methods
- fprintf(out, "\n");
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s_length != %s.size()) {\n",
- attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
- fprintf(out, " return -EINVAL;\n");
- fprintf(out, " }\n");
- }
- }
- fprintf(out, "\n event.begin();\n");
- fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
- attributionDecl.fields.front().name.c_str());
- fprintf(out, " event.begin();\n");
- for (const auto &chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- fprintf(out, " } else {\n");
- fprintf(out, " event << \"\";\n");
- fprintf(out, " }\n");
- } else {
- fprintf(out, " event << %s[i];\n", chainField.name.c_str());
- }
- }
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
- fprintf(out, " event.begin();\n");
- fprintf(out, " event << it.first;\n");
- fprintf(out, " event << it.second;\n");
- fprintf(out, " event.end();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " event.end();\n\n");
- } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);\n",
- argIndex, argIndex);
- } else {
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
- signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_to_modules_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out,
- ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- fprintf(out, " int ret = 0;\n");
-
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", %s",
- chainField.name.c_str());
- } else {
- fprintf(out, ", %s, %s_length",
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
- argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "try_stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
- argIndex = 1;
- fprintf(out, " if (kStatsdEnabled) {\n");
- fprintf(out, " stats_event_list event(kStatsEventTag);\n");
- fprintf(out, " event << android::elapsedRealtimeNano();\n\n");
- fprintf(out, " event << code;\n\n");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (argIndex == 1) {
- fprintf(out, " event.begin();\n\n");
- fprintf(out, " event.begin();\n");
- }
- if (*arg == JAVA_TYPE_STRING) {
- fprintf(out, " if (arg%d == NULL) {\n", argIndex);
- fprintf(out, " arg%d = \"\";\n", argIndex);
- fprintf(out, " }\n");
- }
- if (*arg == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out,
- " event.AppendCharArray(arg%d.arg, "
- "arg%d.arg_length);",
- argIndex, argIndex);
- } else {
- fprintf(out, " event << arg%d;\n", argIndex);
- }
- if (argIndex == 2) {
- fprintf(out, " event.end();\n\n");
- fprintf(out, " event.end();\n\n");
- }
- argIndex++;
- }
-
- fprintf(out, " return event.write(LOG_ID_STATS);\n");
- fprintf(out, " } else {\n");
- fprintf(out, " return 1;\n");
- fprintf(out, " }\n");
- fprintf(out, "}\n");
- fprintf(out, "\n");
- }
-
- for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
- signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
- if (!signature_needed_for_module(signature_it->second, moduleName)) {
- continue;
- }
- vector<java_type_t> signature = signature_it->first;
- int argIndex;
-
- fprintf(out, "int\n");
- fprintf(out, "stats_write_non_chained(int32_t code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- argIndex++;
- }
- fprintf(out, ")\n");
-
- fprintf(out, "{\n");
-
- fprintf(out, " int ret = 0;\n");
- fprintf(out, " for(int retry = 0; retry < 2; ++retry) {\n");
- fprintf(out, " ret = try_stats_write_non_chained(code");
-
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- fprintf(out, ", arg%d", argIndex);
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " if (ret >= 0) { break; }\n");
-
- fprintf(out, " {\n");
- fprintf(out, " std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
- fprintf(out, " if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
- "kMinRetryIntervalNs) break;\n");
- fprintf(out, " lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
- fprintf(out, " }\n");
-
- fprintf(out, " std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
- fprintf(out, " }\n");
- fprintf(out, " if (ret < 0) {\n");
- fprintf(out, " note_log_drop(ret, code);\n");
- fprintf(out, " }\n");
- fprintf(out, " return ret;\n\n");
- fprintf(out, "}\n");
-
- fprintf(out, "\n");
- }
-
-
- // Print footer
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-static void write_cpp_method_header(
- FILE* out,
- const string& method_name,
- const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const AtomDecl &attributionDecl, const string& moduleName) {
-
- for (auto signature_to_modules_it = signatures_to_modules.begin();
- signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
- // Skip if this signature is not needed for the module.
- if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
- continue;
- }
-
- vector<java_type_t> signature = signature_to_modules_it->first;
- fprintf(out, "int %s(int32_t code", method_name.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s",
- cpp_type_name(chainField.javaType), chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType),
- chainField.name.c_str(), chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
-
- }
-}
-
-static int
-write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& cppNamespace)
-{
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#pragma once\n");
- fprintf(out, "\n");
- fprintf(out, "#include <stdint.h>\n");
- fprintf(out, "#include <vector>\n");
- fprintf(out, "#include <map>\n");
- fprintf(out, "#include <set>\n");
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "\n");
- fprintf(out, "/*\n");
- fprintf(out, " * API For logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "\n");
-
- write_native_atom_constants(out, atoms, attributionDecl, moduleName);
-
- // Print constants for the enum values.
- fprintf(out, "//\n");
- fprintf(out, "// Constants for enum values\n");
- fprintf(out, "//\n\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- // Skip if the atom is not needed for the module.
- if (!atom_needed_for_module(*atom, moduleName)) {
- continue;
- }
-
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- fprintf(out, "const int32_t %s__%s__%s = %d;\n",
- make_constant_name(atom->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(),
- value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-
- fprintf(out, "struct BytesField {\n");
- fprintf(out,
- " BytesField(char const* array, size_t len) : arg(array), "
- "arg_length(len) {}\n");
- fprintf(out, " char const* arg;\n");
- fprintf(out, " size_t arg_length;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- // Print write methods
- fprintf(out, "//\n");
- fprintf(out, "// Write methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write", atoms.signatures_to_modules, attributionDecl,
- moduleName);
-
- fprintf(out, "//\n");
- fprintf(out, "// Write flattened methods\n");
- fprintf(out, "//\n");
- write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures_to_modules,
- attributionDecl, moduleName);
-
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
// Hide the JNI write helpers that are not used in the new schema.
// TODO(b/145100015): Remove this and other JNI related functionality once StatsEvent migration is
// complete.
@@ -999,7 +510,9 @@
fprintf(stderr, " required for java with module\n");
fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
fprintf(stderr, " Optional for Java with module.\n");
- fprintf(stderr, " Default is \"StatsLogInternal\"\n");}
+ fprintf(stderr, " Default is \"StatsLogInternal\"\n");
+ fprintf(stderr, " --supportQ Include support for Android Q.\n");
+}
/**
* Do the argument parsing and execute the tasks.
@@ -1020,6 +533,7 @@
string atomsInfoCppHeaderImport = DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT;
string javaPackage = DEFAULT_JAVA_PACKAGE;
string javaClass = DEFAULT_JAVA_CLASS;
+ bool supportQ = false;
int index = 1;
while (index < argc) {
@@ -1110,6 +624,8 @@
return 1;
}
atomsInfoCppHeaderImport = argv[index];
+ } else if (0 == strcmp("--supportQ", argv[index])) {
+ supportQ = true;
}
index++;
@@ -1125,6 +641,12 @@
return 1;
}
+ if (DEFAULT_MODULE_NAME == moduleName && supportQ) {
+ // Support for Q schema is not needed for default module.
+ fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
+ return 1;
+ }
+
// Collate the parameters
Atoms atoms;
int errorCount = collate_atoms(Atom::descriptor(), &atoms);
@@ -1179,7 +701,7 @@
return 1;
}
errorCount = android::stats_log_api_gen::write_stats_log_cpp(
- out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport);
+ out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport, supportQ);
fclose(out);
}
@@ -1227,7 +749,7 @@
javaPackage = "android.util";
}
errorCount = android::stats_log_api_gen::write_stats_log_java(
- out, atoms, attributionDecl, moduleName, javaClass, javaPackage);
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
#endif
fclose(out);
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
new file mode 100644
index 0000000..c7a34fe
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer.h"
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+#if !defined(STATS_SCHEMA_LEGACY)
+static void write_native_key_value_pairs_for_type(FILE* out, const int argIndex,
+ const int typeIndex, const string& type, const string& valueFieldName) {
+ fprintf(out, " for (const auto& it : arg%d_%d) {\n", argIndex, typeIndex);
+ fprintf(out, " pairs.push_back("
+ "{ .key = it.first, .valueType = %s, .%s = it.second });\n",
+ type.c_str(), valueFieldName.c_str());
+ fprintf(out, " }\n");
+
+}
+
+static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const bool supportQ) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "int stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ if (supportQ) {
+ fprintf(out, " StatsEventCompat event;\n");
+ fprintf(out, " event.setAtomId(code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
+ uidName, uidName, tagName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " event.writeKeyValuePairs("
+ "arg%d_1, arg%d_2, arg%d_3, arg%d_4);\n",
+ argIndex, argIndex, argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " event.writeBool(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " event.writeString(arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " return event.writeToSocket();\n");
+ } else {
+ fprintf(out, " struct stats_event* event = stats_event_obtain();\n");
+ fprintf(out, " stats_event_set_atom_id(event, code);\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out,
+ " stats_event_write_attribution_chain(event, "
+ "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
+ "static_cast<uint8_t>(%s_length));\n",
+ uidName, tagName, uidName);
+ break;
+ }
+ case JAVA_TYPE_KEY_VALUE_PAIR:
+ fprintf(out, " std::vector<key_value_pair> pairs;\n");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 1, "INT32_TYPE", "int32Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 2, "INT64_TYPE", "int64Value");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 3, "STRING_TYPE", "stringValue");
+ write_native_key_value_pairs_for_type(
+ out, argIndex, 4, "FLOAT_TYPE", "floatValue");
+ fprintf(out,
+ " stats_event_write_key_value_pairs(event, pairs.data(), "
+ "static_cast<uint8_t>(pairs.size()));\n");
+ break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out,
+ " stats_event_write_byte_array(event, "
+ "reinterpret_cast<const uint8_t*>(arg%d.arg), arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " stats_event_write_bool(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " stats_event_write_int32(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " stats_event_write_float(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " stats_event_write_int64(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " stats_event_write_string8(event, arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE.
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ argIndex++;
+ }
+ fprintf(out, " const int ret = stats_event_write(event);\n");
+ fprintf(out, " stats_event_release(event);\n");
+ fprintf(out, " return ret;\n");
+ }
+ fprintf(out, "}\n\n");
+ }
+ return 0;
+}
+
+static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "int stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ vector<java_type_t> newSignature;
+
+ // First two args form the attribution node so size goes down by 1.
+ newSignature.reserve(signature.size() - 1);
+
+ // First arg is Attribution Chain.
+ newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
+
+ // Followed by the originial signature except the first 2 args.
+ newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
+
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
+ fprintf(out, " const size_t %s_length = 1;\n", uidName);
+ fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
+ fprintf(out, " return ");
+ write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
+
+ fprintf(out, "}\n\n");
+ }
+
+}
+#endif
+
+static void write_native_method_header(
+ FILE* out,
+ const string& methodName,
+ const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+ const AtomDecl &attributionDecl, const string& moduleName) {
+
+ for (auto signature_to_modules_it = signatures_to_modules.begin();
+ signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+ // Skip if this signature is not needed for the module.
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+
+ vector<java_type_t> signature = signature_to_modules_it->first;
+ write_native_method_signature(out, methodName, signature, attributionDecl, ";");
+ }
+}
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace,
+ const string& importHeader, const bool supportQ) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+
+ fprintf(out, "#include <%s>\n", importHeader.c_str());
+#if defined(STATS_SCHEMA_LEGACY)
+ (void)supportQ; // Workaround for unused parameter error.
+ write_native_cpp_includes_q(out);
+#else
+ if (supportQ) {
+ fprintf(out, "#include <StatsEventCompat.h>\n");
+ } else {
+ fprintf(out, "#include <stats_event.h>\n");
+ }
+#endif
+
+ fprintf(out, "\n");
+ write_namespace(out, cppNamespace);
+
+#if defined(STATS_SCHEMA_LEGACY)
+ write_native_stats_log_cpp_globals_q(out);
+ write_native_get_timestamp_ns_q(out);
+ write_native_try_stats_write_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_methods_q(out, "int stats_write", atoms, attributionDecl, moduleName,
+ "try_stats_write");
+ write_native_try_stats_write_non_chained_methods_q(out, atoms, attributionDecl, moduleName);
+ write_native_stats_write_non_chained_methods_q(out, "int stats_write_non_chained", atoms,
+ attributionDecl, moduleName, "try_stats_write_non_chained");
+#else
+ write_native_stats_write_methods(out, atoms, attributionDecl, moduleName, supportQ);
+ write_native_stats_write_non_chained_methods(out, atoms, attributionDecl, moduleName);
+#endif
+
+ // Print footer
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "#pragma once\n");
+ fprintf(out, "\n");
+ fprintf(out, "#include <stdint.h>\n");
+ fprintf(out, "#include <vector>\n");
+ fprintf(out, "#include <map>\n");
+ fprintf(out, "#include <set>\n");
+ fprintf(out, "\n");
+
+ write_namespace(out, cppNamespace);
+ fprintf(out, "\n");
+ fprintf(out, "/*\n");
+ fprintf(out, " * API For logging statistics events.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "\n");
+
+ write_native_atom_constants(out, atoms, attributionDecl, moduleName);
+
+ // Print constants for the enum values.
+ fprintf(out, "//\n");
+ fprintf(out, "// Constants for enum values\n");
+ fprintf(out, "//\n\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ // Skip if the atom is not needed for the module.
+ if (!atom_needed_for_module(*atom, moduleName)) {
+ continue;
+ }
+
+ for (vector<AtomField>::const_iterator field = atom->fields.begin();
+ field != atom->fields.end(); field++) {
+ if (field->javaType == JAVA_TYPE_ENUM) {
+ fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+ field->name.c_str());
+ for (map<int, string>::const_iterator value = field->enumValues.begin();
+ value != field->enumValues.end(); value++) {
+ fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+ make_constant_name(atom->message).c_str(),
+ make_constant_name(field->name).c_str(),
+ make_constant_name(value->second).c_str(),
+ value->first);
+ }
+ fprintf(out, "\n");
+ }
+ }
+ }
+
+ fprintf(out, "struct BytesField {\n");
+ fprintf(out,
+ " BytesField(char const* array, size_t len) : arg(array), "
+ "arg_length(len) {}\n");
+ fprintf(out, " char const* arg;\n");
+ fprintf(out, " size_t arg_length;\n");
+ fprintf(out, "};\n");
+ fprintf(out, "\n");
+
+ // Print write methods
+ fprintf(out, "//\n");
+ fprintf(out, "// Write methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write", atoms.signatures_to_modules, attributionDecl,
+ moduleName);
+
+ fprintf(out, "//\n");
+ fprintf(out, "// Write flattened methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "int stats_write_non_chained",
+ atoms.non_chained_signatures_to_modules, attributionDecl, moduleName);
+
+ fprintf(out, "\n");
+ write_closing_namespace(out, cppNamespace);
+
+ return 0;
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
new file mode 100644
index 0000000..aafa96e
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace, const string& importHeader,
+ const bool supportQ);
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const string& moduleName, const string& cppNamespace);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.cpp b/tools/stats_log_api_gen/native_writer_q.cpp
new file mode 100644
index 0000000..299873d
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void write_native_stats_write_body_q(FILE* out, const vector<java_type_t>& signature,
+ const AtomDecl& attributionDecl, const string& indent, const string& tryMethodName) {
+ fprintf(out, "%sint ret = 0;\n", indent.c_str());
+
+ fprintf(out, "%sfor(int retry = 0; retry < 2; ++retry) {\n", indent.c_str());
+ fprintf(out, "%s ret = ", indent.c_str());
+ write_native_method_call(out, tryMethodName, signature, attributionDecl);
+ fprintf(out, "%s if (ret >= 0) { break; }\n", indent.c_str());
+
+ fprintf(out, "%s {\n", indent.c_str());
+ fprintf(out, "%s std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n", indent.c_str());
+ fprintf(out, "%s if ((get_elapsed_realtime_ns() - lastRetryTimestampNs) <= "
+ "kMinRetryIntervalNs) break;\n", indent.c_str());
+ fprintf(out, "%s lastRetryTimestampNs = get_elapsed_realtime_ns();\n",
+ indent.c_str());
+ fprintf(out, "%s }\n", indent.c_str());
+ fprintf(out, "%s std::this_thread::sleep_for(std::chrono::milliseconds(10));\n",
+ indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sif (ret < 0) {\n", indent.c_str());
+ fprintf(out, "%s note_log_drop(ret, code);\n", indent.c_str());
+ fprintf(out, "%s}\n", indent.c_str());
+ fprintf(out, "%sreturn ret;\n", indent.c_str());
+}
+
+void write_native_cpp_includes_q(FILE* out) {
+ fprintf(out, "#include <mutex>\n");
+ fprintf(out, "#include <chrono>\n");
+ fprintf(out, "#include <thread>\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out, "#include <cutils/properties.h>\n");
+ fprintf(out, "#endif\n");
+ fprintf(out, "#include <stats_event_list.h>\n");
+ fprintf(out, "#include <log/log.h>\n");
+ fprintf(out, "#include <time.h>\n");
+}
+
+void write_native_get_timestamp_ns_q(FILE* out) {
+ fprintf(out, "\n");
+ fprintf(out, "static int64_t get_elapsed_realtime_ns() {\n");
+ fprintf(out, " struct timespec t;\n");
+ fprintf(out, " t.tv_sec = t.tv_nsec = 0;\n");
+ fprintf(out, " clock_gettime(CLOCK_BOOTTIME, &t);\n");
+ fprintf(out, " return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;\n");
+ fprintf(out, "}\n");
+}
+
+void write_native_stats_log_cpp_globals_q(FILE* out) {
+ fprintf(out, "// the single event tag id for all stats logs\n");
+ fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
+ fprintf(out,
+ "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "const static bool kStatsdEnabled = false;\n");
+ fprintf(out, "#endif\n");
+
+ fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
+ fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
+ fprintf(out, "static std::mutex mLogdRetryMutex;\n");
+}
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ fprintf(out, "\n");
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s_length != %s.size()) {\n",
+ attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
+ fprintf(out, " return -EINVAL;\n");
+ fprintf(out, " }\n");
+ }
+ }
+ fprintf(out, "\n event.begin();\n");
+ fprintf(out, " for (size_t i = 0; i < %s_length; ++i) {\n",
+ attributionDecl.fields.front().name.c_str());
+ fprintf(out, " event.begin();\n");
+ for (const auto &chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, " if (%s[i] != NULL) {\n", chainField.name.c_str());
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ fprintf(out, " } else {\n");
+ fprintf(out, " event << \"\";\n");
+ fprintf(out, " }\n");
+ } else {
+ fprintf(out, " event << %s[i];\n", chainField.name.c_str());
+ }
+ }
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " for (const auto& it : arg%d_1) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_2) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_3) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " for (const auto& it : arg%d_4) {\n", argIndex);
+ fprintf(out, " event.begin();\n");
+ fprintf(out, " event << it.first;\n");
+ fprintf(out, " event << it.second;\n");
+ fprintf(out, " event.end();\n");
+ fprintf(out, " }\n");
+
+ fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+
+}
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName) {
+ for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+ signature_to_modules_it != atoms.signatures_to_modules.end();
+ signature_to_modules_it++) {
+ if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_to_modules_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+ write_native_stats_write_body_q(out, signature, attributionDecl, " ", tryMethodName);
+ fprintf(out, "}\n\n");
+ }
+}
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName) {
+ for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+ signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+ if (!signature_needed_for_module(signature_it->second, moduleName)) {
+ continue;
+ }
+ vector<java_type_t> signature = signature_it->first;
+
+ write_native_method_signature(out, "static int try_stats_write_non_chained", signature,
+ attributionDecl, " {");
+
+ int argIndex = 1;
+ fprintf(out, " if (kStatsdEnabled) {\n");
+ fprintf(out, " stats_event_list event(kStatsEventTag);\n");
+ fprintf(out, " event << get_elapsed_realtime_ns();\n\n");
+ fprintf(out, " event << code;\n\n");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (argIndex == 1) {
+ fprintf(out, " event.begin();\n\n");
+ fprintf(out, " event.begin();\n");
+ }
+ if (*arg == JAVA_TYPE_STRING) {
+ fprintf(out, " if (arg%d == NULL) {\n", argIndex);
+ fprintf(out, " arg%d = \"\";\n", argIndex);
+ fprintf(out, " }\n");
+ }
+ if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d.arg, "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ } else {
+ fprintf(out, " event << arg%d;\n", argIndex);
+ }
+ if (argIndex == 2) {
+ fprintf(out, " event.end();\n\n");
+ fprintf(out, " event.end();\n\n");
+ }
+ argIndex++;
+ }
+
+ fprintf(out, " return event.write(LOG_ID_STATS);\n");
+ fprintf(out, " } else {\n");
+ fprintf(out, " return 1;\n");
+ fprintf(out, " }\n");
+ fprintf(out, "}\n");
+ fprintf(out, "\n");
+ }
+}
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.h b/tools/stats_log_api_gen/native_writer_q.h
new file mode 100644
index 0000000..a2ab1ae
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+void write_native_cpp_includes_q(FILE* out);
+
+void write_native_stats_log_cpp_globals_q(FILE* out);
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName);
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+ const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+ const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+ const string& tryMethodName);
+
+void write_native_get_timestamp_ns_q(FILE* out);
+
+} // namespace stats_log_api_gen
+} // namespace android
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index c3e70382..c9a4763 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -229,8 +229,8 @@
message ModuleAtoms {
oneof event {
- ModuleOneAtom module_one_atom = 1 [(android.os.statsd.log_from_module) = "module1"];
- ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.log_from_module) = "module2"];
+ ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"];
+ ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"];
NoModuleAtom no_module_atom = 3;
}
-}
\ No newline at end of file
+}
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index d6cfe95..c65d190 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -204,6 +204,65 @@
fprintf(out, "\n");
}
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer) {
+ fprintf(out, "%s(int32_t code", methodName.c_str());
+ int argIndex = 1;
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", const std::vector<%s>& %s",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", const %s* %s, size_t %s_length",
+ cpp_type_name(chainField.javaType),
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+ "const std::map<int, int64_t>& arg%d_2, "
+ "const std::map<int, char const*>& arg%d_3, "
+ "const std::map<int, float>& arg%d_4",
+ argIndex, argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ")%s\n", closer.c_str());
+}
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex) {
+ fprintf(out, "%s(code", methodName.c_str());
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+ for (auto chainField : attributionDecl.fields) {
+ if (chainField.javaType == JAVA_TYPE_STRING) {
+ fprintf(out, ", %s",
+ chainField.name.c_str());
+ } else {
+ fprintf(out, ", %s, %s_length",
+ chainField.name.c_str(), chainField.name.c_str());
+ }
+ }
+ } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+ fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
+ argIndex, argIndex, argIndex);
+ } else {
+ fprintf(out, ", arg%d", argIndex);
+ }
+ argIndex++;
+ }
+ fprintf(out, ");\n");
+}
+
// Java
void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) {
fprintf(out, " // Constants for atom codes.\n");
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index a89387f..50737a6 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -56,8 +56,14 @@
void write_closing_namespace(FILE* out, const string& cppNamespaces);
void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& moduleName
-);
+ const string& moduleName);
+
+void write_native_method_signature(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+ const string& closer);
+
+void write_native_method_call(FILE* out, const string& methodName,
+ const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex = 1);
// Common Java helpers.
void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName);
@@ -69,14 +75,12 @@
int write_java_non_chained_methods(FILE* out, const map<vector<java_type_t>,
set<string>>& signatures_to_modules,
- const string& moduleName
-);
+ const string& moduleName);
int write_java_work_source_methods(
FILE* out,
const map<vector<java_type_t>, set<string>>& signatures_to_modules,
- const string& moduleName
-);
+ const string& moduleName);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/wifi/Android.bp b/wifi/Android.bp
index fb1f866..35a892a 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -42,11 +42,21 @@
srcs: ["java/android/net/wifi/WifiAnnotations.java"],
}
+// list of tests that are allowed to access @hide APIs from framework-wifi
+test_access_hidden_api_whitelist = [
+ "//frameworks/base/wifi/tests",
+ "//frameworks/opt/net/wifi/tests/wifitests:__subpackages__",
+
+ "//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests",
+]
+
java_library {
name: "framework-wifi",
- sdk_version: "core_platform", // TODO(b/140299412) should be core_current
+ // TODO(b/140299412) should be core_current once we build against framework-system-stubs
+ sdk_version: "core_platform",
libs: [
- "framework-minus-apex", // TODO(b/140299412) should be framework-system-stubs
+ // TODO(b/140299412) should be framework-system-stubs once we fix all @hide dependencies
+ "framework-minus-apex",
],
srcs: [
":framework-wifi-updatable-sources",
@@ -54,7 +64,12 @@
installable: true,
optimize: {
enabled: false
- }
+ },
+ visibility: [
+ "//frameworks/base", // TODO(b/140299412) remove once all dependencies are fixed
+ "//frameworks/opt/net/wifi/service:__subpackages__",
+ ] + test_access_hidden_api_whitelist,
+ plugins: ["java_api_finder"],
}
droidstubs {
@@ -84,3 +99,16 @@
installable: false,
}
+// defaults for tests that need to build against framework-wifi's @hide APIs
+java_defaults {
+ name: "framework-wifi-test-defaults",
+ sdk_version: "core_platform", // tests can use @CorePlatformApi's
+ libs: [
+ "framework-wifi",
+ "framework-minus-apex",
+
+ // if sdk_version="" this gets automatically included, but here we need to add manually.
+ "framework-res",
+ ],
+ visibility: test_access_hidden_api_whitelist,
+}
diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java
index 3e09580..3794566 100644
--- a/wifi/java/android/net/wifi/WifiClient.java
+++ b/wifi/java/android/net/wifi/WifiClient.java
@@ -22,8 +22,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.Preconditions;
-
import java.util.Objects;
/** @hide */
@@ -46,7 +44,7 @@
/** @hide */
public WifiClient(@NonNull MacAddress macAddress) {
- Preconditions.checkNotNull(macAddress, "mMacAddress must not be null.");
+ Objects.requireNonNull(macAddress, "mMacAddress must not be null.");
this.mMacAddress = macAddress;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e3a945d..2a165d3 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2446,10 +2446,14 @@
return key;
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * Get the IpConfiguration object associated with this WifiConfiguration.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
public IpConfiguration getIpConfiguration() {
- return mIpConfiguration;
+ return new IpConfiguration(mIpConfiguration);
}
/**
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
index be37c22..378549d 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -29,11 +29,11 @@
import android.util.LruCache;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Objects;
/**
* {@link INetworkScoreCache} implementation for Wifi Networks.
@@ -290,7 +290,7 @@
* This cannot be null.
*/
public CacheListener(@NonNull Handler handler) {
- Preconditions.checkNotNull(handler);
+ Objects.requireNonNull(handler);
mHandler = handler;
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 8badcc0..2c39c32a 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -40,7 +40,6 @@
import android.util.SparseArray;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
import java.lang.annotation.Retention;
@@ -48,6 +47,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -840,8 +840,8 @@
@RequiresPermission(Manifest.permission.NETWORK_STACK)
public void registerScanListener(@NonNull @CallbackExecutor Executor executor,
@NonNull ScanListener listener) {
- Preconditions.checkNotNull(executor, "executor cannot be null");
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(executor, "executor cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = addListener(listener, executor);
if (key == INVALID_KEY) return;
validateChannel();
@@ -864,7 +864,7 @@
* #registerScanListener}
*/
public void unregisterScanListener(@NonNull ScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -894,7 +894,7 @@
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startBackgroundScan(ScanSettings settings, ScanListener listener,
WorkSource workSource) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -913,7 +913,7 @@
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopBackgroundScan(ScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -962,7 +962,7 @@
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -981,7 +981,7 @@
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public void stopScan(ScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -1036,8 +1036,8 @@
*/
public void startConnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
PnoScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
+ Objects.requireNonNull(pnoSettings, "pnoSettings cannot be null");
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -1058,8 +1058,8 @@
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
PnoScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
- Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
+ Objects.requireNonNull(pnoSettings, "pnoSettings cannot be null");
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
@@ -1074,7 +1074,7 @@
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public void stopPnoScan(ScanListener listener) {
- Preconditions.checkNotNull(listener, "listener cannot be null");
+ Objects.requireNonNull(listener, "listener cannot be null");
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();