Merge "package-manager: Unhide FEATURE_UWB"
diff --git a/.clang-format b/.clang-format
index 03af56d..d60d33c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -9,5 +9,17 @@
ConstructorInitializerIndentWidth: 6
ContinuationIndentWidth: 8
IndentWidth: 4
+JavaImportGroups:
+- android
+- androidx
+- com.android
+- dalvik
+- libcore
+- com
+- junit
+- net
+- org
+- java
+- javax
PenaltyBreakBeforeFirstCallParameter: 100000
SpacesBeforeTrailingComments: 1
diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp
index 98e4f45..9366ff2d 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -62,4 +62,10 @@
test_suites: ["device-tests"],
certificate: "platform",
+
+ errorprone: {
+ javacflags: [
+ "-Xep:ReturnValueIgnored:WARN",
+ ],
+ },
}
diff --git a/apct-tests/perftests/core/src/android/libcore/ReferencePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ReferencePerfTest.java
index 2ef68ca..05a3e12 100644
--- a/apct-tests/perftests/core/src/android/libcore/ReferencePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ReferencePerfTest.java
@@ -118,7 +118,7 @@
int got = count.get();
if (n != got) {
throw new IllegalStateException(
- String.format("Only %i of %i objects finalized?", got, n));
+ String.format("Only %d of %d objects finalized?", got, n));
}
}
}
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 d9fe30d..e0d1a30 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -569,7 +569,7 @@
public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
@VisibleForTesting
static final long DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS = 5 * MINUTE_IN_MILLIS;
- static final boolean DEFAULT_PERSIST_IN_SPLIT_FILES = false;
+ static final boolean DEFAULT_PERSIST_IN_SPLIT_FILES = true;
private static final boolean DEFAULT_USE_TARE_POLICY = false;
/**
diff --git a/core/api/current.txt b/core/api/current.txt
index f201d81..6a875b8 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -91,6 +91,18 @@
field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
+ field public static final String FOREGROUND_SERVICE_CAMERA = "android.permission.FOREGROUND_SERVICE_CAMERA";
+ field public static final String FOREGROUND_SERVICE_CONNECTED_DEVICE = "android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE";
+ field public static final String FOREGROUND_SERVICE_DATA_SYNC = "android.permission.FOREGROUND_SERVICE_DATA_SYNC";
+ field public static final String FOREGROUND_SERVICE_HEALTH = "android.permission.FOREGROUND_SERVICE_HEALTH";
+ field public static final String FOREGROUND_SERVICE_LOCATION = "android.permission.FOREGROUND_SERVICE_LOCATION";
+ field public static final String FOREGROUND_SERVICE_MEDIA_PLAYBACK = "android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK";
+ field public static final String FOREGROUND_SERVICE_MEDIA_PROJECTION = "android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION";
+ field public static final String FOREGROUND_SERVICE_MICROPHONE = "android.permission.FOREGROUND_SERVICE_MICROPHONE";
+ field public static final String FOREGROUND_SERVICE_PHONE_CALL = "android.permission.FOREGROUND_SERVICE_PHONE_CALL";
+ field public static final String FOREGROUND_SERVICE_REMOTE_MESSAGING = "android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING";
+ field public static final String FOREGROUND_SERVICE_SPECIAL_USE = "android.permission.FOREGROUND_SERVICE_SPECIAL_USE";
+ field public static final String FOREGROUND_SERVICE_SYSTEM_EXEMPTED = "android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED";
field public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
@@ -6946,7 +6958,7 @@
method public void onTrimMemory(int);
method public boolean onUnbind(android.content.Intent);
method public final void startForeground(int, android.app.Notification);
- method public final void startForeground(int, @NonNull android.app.Notification, int);
+ method public final void startForeground(int, @NonNull android.app.Notification, @RequiresPermission int);
method @Deprecated public final void stopForeground(boolean);
method public final void stopForeground(int);
method public final void stopSelf();
@@ -12195,6 +12207,7 @@
field public static final int PERMISSION_DENIED = -1; // 0xffffffff
field public static final int PERMISSION_GRANTED = 0; // 0x0
field public static final String PROPERTY_MEDIA_CAPABILITIES = "android.media.PROPERTY_MEDIA_CAPABILITIES";
+ field public static final String PROPERTY_SPECIAL_USE_FGS_SUBTYPE = "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
field public static final int SIGNATURE_MATCH = 0; // 0x0
field public static final int SIGNATURE_NEITHER_SIGNED = 1; // 0x1
@@ -12408,16 +12421,20 @@
field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
field public static final int FLAG_USE_APP_ZYGOTE = 8; // 0x8
- field public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40
- field public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10
- field public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1
- field public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CAMERA}, anyOf={android.Manifest.permission.CAMERA}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10
+ field @Deprecated @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_HEALTH}, anyOf={android.Manifest.permission.ACTIVITY_RECOGNITION, android.Manifest.permission.BODY_SENSORS, android.Manifest.permission.HIGH_SAMPLING_RATE_SENSORS}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 256; // 0x100
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_LOCATION}, anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8
field public static final int FOREGROUND_SERVICE_TYPE_MANIFEST = -1; // 0xffffffff
- field public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 2; // 0x2
- field public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 32; // 0x20
- field public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 128; // 0x80
- field public static final int FOREGROUND_SERVICE_TYPE_NONE = 0; // 0x0
- field public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 4; // 0x4
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 2; // 0x2
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 32; // 0x20
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_MICROPHONE}, anyOf={android.Manifest.permission.CAPTURE_AUDIO_OUTPUT, android.Manifest.permission.RECORD_AUDIO}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 128; // 0x80
+ field @Deprecated public static final int FOREGROUND_SERVICE_TYPE_NONE = 0; // 0x0
+ field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_PHONE_CALL}, anyOf={android.Manifest.permission.MANAGE_OWN_CALLS}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 4; // 0x4
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING = 512; // 0x200
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_SPECIAL_USE = 1073741824; // 0x40000000
+ field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED = 1024; // 0x400
field public int flags;
field public String permission;
}
@@ -41896,6 +41913,7 @@
field public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
field public static final String KEY_VONR_ENABLED_BOOL = "vonr_enabled_bool";
+ field public static final String KEY_VONR_ON_BY_DEFAULT_BOOL = "vonr_on_by_default_bool";
field public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool";
field public static final String KEY_VT_UPGRADE_SUPPORTED_FOR_DOWNGRADED_RTT_CALL_BOOL = "vt_upgrade_supported_for_downgraded_rtt_call";
field public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 4eeb42f..ce1eff1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -7156,6 +7156,7 @@
public class Tuner implements java.lang.AutoCloseable {
ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @Nullable String, int);
+ method public int applyFrontend(@NonNull android.media.tv.tuner.frontend.FrontendInfo);
method public int cancelScanning();
method public int cancelTuning();
method public void clearOnTuneEventListener();
@@ -7186,7 +7187,6 @@
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_SHARED_FILTER) public static android.media.tv.tuner.filter.SharedFilter openSharedFilter(@NonNull android.content.Context, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.filter.SharedFilterCallback);
method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
method public int removeOutputPid(@IntRange(from=0) int);
- method public int requestFrontendById(int);
method public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
method public int setLnaEnabled(boolean);
method public int setMaxNumberOfFrontends(int, @IntRange(from=0) int);
@@ -9969,9 +9969,10 @@
method public boolean isCloneProfile();
method public boolean isCredentialSharableWithParent();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isGuestUser();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isMainUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isManagedProfile(int);
method public boolean isMediaSharedWithParent();
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public boolean isPrimaryUser();
method public static boolean isRemoveResultSuccessful(int);
method public boolean isRestrictedProfile();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public boolean isRestrictedProfile(@NonNull android.os.UserHandle);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index d1c1a17..3fee610 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -905,6 +905,7 @@
method public boolean isFull();
method public boolean isGuest();
method public boolean isInitialized();
+ method public boolean isMain();
method public boolean isManagedProfile();
method public boolean isPrimary();
method public boolean isProfile();
@@ -923,6 +924,7 @@
field public static final int FLAG_FULL = 1024; // 0x400
field @Deprecated public static final int FLAG_GUEST = 4; // 0x4
field public static final int FLAG_INITIALIZED = 16; // 0x10
+ field public static final int FLAG_MAIN = 16384; // 0x4000
field @Deprecated public static final int FLAG_MANAGED_PROFILE = 32; // 0x20
field public static final int FLAG_PRIMARY = 1; // 0x1
field public static final int FLAG_PROFILE = 4096; // 0x1000
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 0f4644c..1b3282e 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1398,9 +1398,18 @@
*/
public static final int OP_READ_WRITE_HEALTH_DATA = AppProtoEnums.APP_OP_READ_WRITE_HEALTH_DATA;
+ /**
+ * Use foreground service with the type
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE}.
+ *
+ * @hide
+ */
+ public static final int OP_FOREGROUND_SERVICE_SPECIAL_USE =
+ AppProtoEnums.APP_OP_FOREGROUND_SERVICE_SPECIAL_USE;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 127;
+ public static final int _NUM_OP = 128;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1930,6 +1939,14 @@
public static final String OPSTR_SYSTEM_EXEMPT_FROM_FORCED_APP_STANDBY =
"android:system_exempt_from_forced_app_standby";
+ /**
+ * Start a foreground service with the type "specialUse".
+ *
+ * @hide
+ */
+ public static final String OPSTR_FOREGROUND_SERVICE_SPECIAL_USE =
+ "android:foreground_service_special_use";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2026,6 +2043,7 @@
OP_TURN_SCREEN_ON,
OP_RUN_LONG_JOBS,
OP_READ_MEDIA_VISUAL_USER_SELECTED,
+ OP_FOREGROUND_SERVICE_SPECIAL_USE,
};
static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
@@ -2419,7 +2437,10 @@
OPSTR_SYSTEM_EXEMPT_FROM_FORCED_APP_STANDBY,
"SYSTEM_EXEMPT_FROM_FORCED_APP_STANDBY").build(),
new AppOpInfo.Builder(OP_READ_WRITE_HEALTH_DATA, OPSTR_READ_WRITE_HEALTH_DATA,
- "READ_WRITE_HEALTH_DATA").setDefaultMode(AppOpsManager.MODE_ALLOWED).build()
+ "READ_WRITE_HEALTH_DATA").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+ new AppOpInfo.Builder(OP_FOREGROUND_SERVICE_SPECIAL_USE,
+ OPSTR_FOREGROUND_SERVICE_SPECIAL_USE, "FOREGROUND_SERVICE_SPECIAL_USE")
+ .setPermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE).build(),
};
// The number of longs needed to form a full bitmask of app ops
@@ -8486,8 +8507,9 @@
*/
public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
@Nullable String message, boolean skipProxyOperation) {
- return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation,
- ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE);
+ return startProxyOpNoThrow(attributionSource.getToken(), op, attributionSource, message,
+ skipProxyOperation, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE,
+ ATTRIBUTION_CHAIN_ID_NONE);
}
/**
@@ -8499,7 +8521,8 @@
*
* @hide
*/
- public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource,
+ public int startProxyOpNoThrow(@NonNull IBinder clientId, int op,
+ @NonNull AttributionSource attributionSource,
@Nullable String message, boolean skipProxyOperation, @AttributionFlags
int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags,
int attributionChainId) {
@@ -8517,7 +8540,7 @@
}
}
- SyncNotedAppOp syncOp = mService.startProxyOperation(op,
+ SyncNotedAppOp syncOp = mService.startProxyOperation(clientId, op,
attributionSource, false, collectionMode == COLLECT_ASYNC, message,
shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
proxiedAttributionFlags, attributionChainId);
@@ -8615,9 +8638,10 @@
*/
public void finishProxyOp(@NonNull String op, int proxiedUid,
@NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) {
- finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(),
+ IBinder token = mContext.getAttributionSource().getToken();
+ finishProxyOp(token, op, new AttributionSource(mContext.getAttributionSource(),
new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag,
- mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false);
+ token)), /*skipProxyOperation*/ false);
}
/**
@@ -8632,10 +8656,11 @@
*
* @hide
*/
- public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource,
- boolean skipProxyOperation) {
+ public void finishProxyOp(@NonNull IBinder clientId, @NonNull String op,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
try {
- mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation);
+ mService.finishProxyOperation(clientId, strOpToOp(op), attributionSource,
+ skipProxyOperation);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 4d6e4ae..43023fe 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -26,13 +26,11 @@
import android.util.SparseIntArray;
import com.android.internal.app.IAppOpsCallback;
-import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
import com.android.internal.util.function.QuintFunction;
-import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.UndecFunction;
/**
@@ -135,6 +133,7 @@
/**
* Allows overriding start proxy operation behavior.
*
+ * @param clientId The client calling start, represented by an IBinder
* @param code The op code to start.
* @param attributionSource The permission identity of the caller.
* @param startIfModeDefault Whether to start the op of the mode is default.
@@ -148,11 +147,12 @@
* @param superImpl The super implementation.
* @return The app op note result.
*/
- SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource,
- boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags
- int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags,
- int attributionChainId, @NonNull DecFunction<Integer, AttributionSource, Boolean,
+ SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
+ @AttributionFlags int proxiedAttributionFlags, int attributionChainId,
+ @NonNull UndecFunction<IBinder, Integer, AttributionSource, Boolean,
Boolean, String, Boolean, Boolean, Integer, Integer, Integer,
SyncNotedAppOp> superImpl);
@@ -176,10 +176,15 @@
*
* @param code The op code to finish.
* @param attributionSource The permission identity of the caller.
+ * @param skipProxyOperation Whether to skip the proxy in the proxy/proxied operation
+ * @param clientId The client calling finishProxyOperation
+ * @param superImpl The "standard" implementation to potentially call
*/
- void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
+ void finishProxyOperation(@NonNull IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource,
boolean skipProxyOperation,
- @NonNull TriFunction<Integer, AttributionSource, Boolean, Void> superImpl);
+ @NonNull QuadFunction<IBinder, Integer, AttributionSource, Boolean,
+ Void> superImpl);
}
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 10cdf53..042bdd7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1814,12 +1814,6 @@
}
}
try {
- ActivityThread thread = ActivityThread.currentActivityThread();
- Instrumentation instrumentation = thread.getInstrumentation();
- if (instrumentation.isInstrumenting()
- && ((flags & Context.RECEIVER_NOT_EXPORTED) == 0)) {
- flags = flags | Context.RECEIVER_EXPORTED;
- }
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(),
AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId,
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java
new file mode 100644
index 0000000..eccc563
--- /dev/null
+++ b/core/java/android/app/ForegroundServiceTypePolicy.java
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (C) 2022 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.app;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_HEALTH;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED;
+
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.app.compat.CompatChanges;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.Overridable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.pm.ServiceInfo.ForegroundServiceType;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArraySet;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.compat.CompatibilityChangeConfig;
+import com.android.internal.compat.IPlatformCompat;
+import com.android.internal.util.ArrayUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Optional;
+
+/**
+ * This class enforces the policies around the foreground service types.
+ *
+ * @hide
+ */
+public abstract class ForegroundServiceTypePolicy {
+ static final String TAG = "ForegroundServiceTypePolicy";
+ static final boolean DEBUG_FOREGROUND_SERVICE_TYPE_POLICY = false;
+
+ /**
+ * The FGS type enforcement:
+ * deprecating the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ *
+ * <p>Starting a FGS with this type (equivalent of no type) from apps with
+ * targetSdkVersion {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
+ * result in a warning in the log.</p>
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU)
+ @Overridable
+ public static final long FGS_TYPE_NONE_DEPRECATION_CHANGE_ID = 255042465L;
+
+ /**
+ * The FGS type enforcement:
+ * disabling the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ *
+ * <p>Starting a FGS with this type (equivalent of no type) from apps with
+ * targetSdkVersion {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
+ * result in an exception.</p>
+ *
+ * @hide
+ */
+ // TODO (b/254661666): Change to @EnabledAfter(T)
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long FGS_TYPE_NONE_DISABLED_CHANGE_ID = 255038118L;
+
+ /**
+ * The FGS type enforcement:
+ * deprecating the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC}.
+ *
+ * <p>Starting a FGS with this type from apps with targetSdkVersion
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
+ * result in a warning in the log.</p>
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU)
+ @Overridable
+ public static final long FGS_TYPE_DATA_SYNC_DEPRECATION_CHANGE_ID = 255039210L;
+
+ /**
+ * The FGS type enforcement:
+ * disabling the {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC}.
+ *
+ * <p>Starting a FGS with this type from apps with targetSdkVersion
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later will
+ * result in an exception.</p>
+ *
+ * @hide
+ */
+ // TODO (b/254661666): Change to @EnabledSince(U) in next OS release
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long FGS_TYPE_DATA_SYNC_DISABLED_CHANGE_ID = 255659651L;
+
+ /**
+ * The FGS type enforcement: Starting a FGS from apps with targetSdkVersion
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later but without the required
+ * permissions associated with the FGS type will result in a SecurityException.
+ *
+ * @hide
+ */
+ // TODO (b/254661666): Change to @EnabledAfter(T)
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long FGS_TYPE_PERMISSION_CHANGE_ID = 254662522L;
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_NONE =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_NONE,
+ FGS_TYPE_NONE_DEPRECATION_CHANGE_ID,
+ FGS_TYPE_NONE_DISABLED_CHANGE_ID,
+ null,
+ null
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_DATA_SYNC}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_DATA_SYNC =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_DATA_SYNC,
+ FGS_TYPE_DATA_SYNC_DEPRECATION_CHANGE_ID,
+ FGS_TYPE_DATA_SYNC_DISABLED_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC)
+ }, true),
+ null
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_MEDIA_PLAYBACK =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK)
+ }, true),
+ null
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_PHONE_CALL}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_PHONE_CALL =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_PHONE_CALL,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_PHONE_CALL)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.MANAGE_OWN_CALLS)
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_LOCATION}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_LOCATION =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_LOCATION,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_LOCATION)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.ACCESS_COARSE_LOCATION),
+ new RegularPermission(Manifest.permission.ACCESS_FINE_LOCATION),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_CONNECTED_DEVICE =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.BLUETOOTH_CONNECT),
+ new RegularPermission(Manifest.permission.CHANGE_NETWORK_STATE),
+ new RegularPermission(Manifest.permission.CHANGE_WIFI_STATE),
+ new RegularPermission(Manifest.permission.CHANGE_WIFI_MULTICAST_STATE),
+ new RegularPermission(Manifest.permission.NFC),
+ new RegularPermission(Manifest.permission.TRANSMIT_IR),
+ new UsbDevicePermission(),
+ new UsbAccessoryPermission(),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_MEDIA_PROJECTION =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT),
+ new AppOpPermission(AppOpsManager.OP_PROJECT_MEDIA)
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_CAMERA =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_CAMERA,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_CAMERA)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.CAMERA),
+ new RegularPermission(Manifest.permission.SYSTEM_CAMERA),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_MICROPHONE =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_MICROPHONE,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_MICROPHONE)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD),
+ new RegularPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT),
+ new RegularPermission(Manifest.permission.CAPTURE_MEDIA_OUTPUT),
+ new RegularPermission(Manifest.permission.CAPTURE_TUNER_AUDIO_INPUT),
+ new RegularPermission(Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT),
+ new RegularPermission(Manifest.permission.RECORD_AUDIO),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_HEALTH}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_HEALTH =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_HEALTH,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_HEALTH)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.ACTIVITY_RECOGNITION),
+ new RegularPermission(Manifest.permission.BODY_SENSORS),
+ new RegularPermission(Manifest.permission.HIGH_SAMPLING_RATE_SENSORS),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_REMOTE_MESSAGING =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING)
+ }, true),
+ null
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_SYSTEM_EXEMPTED =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED)
+ }, true),
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.SCHEDULE_EXACT_ALARM),
+ new RegularPermission(Manifest.permission.USE_EXACT_ALARM),
+ new AppOpPermission(AppOpsManager.OP_ACTIVATE_VPN),
+ new AppOpPermission(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN),
+ }, false)
+ );
+
+ /**
+ * The policy for the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE}.
+ *
+ * @hide
+ */
+ public static final @NonNull ForegroundServiceTypePolicyInfo FGS_TYPE_POLICY_SPECIAL_USE =
+ new ForegroundServiceTypePolicyInfo(
+ FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ ForegroundServiceTypePolicyInfo.INVALID_CHANGE_ID,
+ new ForegroundServiceTypePermissions(new ForegroundServiceTypePermission[] {
+ new RegularPermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE)
+ }, true),
+ null
+ );
+
+ /**
+ * Foreground service policy check result code: this one is not actually being used.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_UNKNOWN =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_UNKNOWN;
+
+ /**
+ * Foreground service policy check result code: okay to go.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_OK =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_OK;
+
+ /**
+ * Foreground service policy check result code: this foreground service type is deprecated.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_DEPRECATED =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_DEPRECATED;
+
+ /**
+ * Foreground service policy check result code: this foreground service type is disabled.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_DISABLED =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_DISABLED;
+
+ /**
+ * Foreground service policy check result code: the caller doesn't have permission to start
+ * foreground service with this type, but the policy is permissive.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE;
+
+ /**
+ * Foreground service policy check result code: the caller doesn't have permission to start
+ * foreground service with this type, and the policy is enforced.
+ *
+ * @hide
+ */
+ public static final int FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED =
+ AppProtoEnums.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED;
+
+ /**
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "FGS_TYPE_POLICY_CHECK_" }, value = {
+ FGS_TYPE_POLICY_CHECK_UNKNOWN,
+ FGS_TYPE_POLICY_CHECK_OK,
+ FGS_TYPE_POLICY_CHECK_DEPRECATED,
+ FGS_TYPE_POLICY_CHECK_DISABLED,
+ FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE,
+ FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ForegroundServicePolicyCheckCode{}
+
+ /**
+ * @return The policy info for the given type.
+ */
+ @NonNull
+ public abstract ForegroundServiceTypePolicyInfo getForegroundServiceTypePolicyInfo(
+ @ForegroundServiceType int type, @ForegroundServiceType int defaultToType);
+
+ /**
+ * Run check on the foreground service type policy for the given uid/pid
+ *
+ * @hide
+ */
+ @ForegroundServicePolicyCheckCode
+ public abstract int checkForegroundServiceTypePolicy(@NonNull Context context,
+ @NonNull String packageName, int callerUid, int callerPid, boolean allowWhileInUse,
+ @NonNull ForegroundServiceTypePolicyInfo policy);
+
+ @GuardedBy("sLock")
+ private static ForegroundServiceTypePolicy sDefaultForegroundServiceTypePolicy = null;
+
+ private static final Object sLock = new Object();
+
+ /**
+ * Return the default policy for FGS type.
+ */
+ public static @NonNull ForegroundServiceTypePolicy getDefaultPolicy() {
+ synchronized (sLock) {
+ if (sDefaultForegroundServiceTypePolicy == null) {
+ sDefaultForegroundServiceTypePolicy = new DefaultForegroundServiceTypePolicy();
+ }
+ return sDefaultForegroundServiceTypePolicy;
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @hide
+ */
+ public ForegroundServiceTypePolicy() {
+ }
+
+ /**
+ * This class represents the policy for a specific FGS service type.
+ *
+ * @hide
+ */
+ public static final class ForegroundServiceTypePolicyInfo {
+ /**
+ * The foreground service type.
+ */
+ final @ForegroundServiceType int mType;
+
+ /**
+ * The change id to tell if this FGS type is deprecated.
+ *
+ * <p>A 0 indicates it's not deprecated.</p>
+ */
+ final long mDeprecationChangeId;
+
+ /**
+ * The change id to tell if this FGS type is disabled.
+ *
+ * <p>A 0 indicates it's not disabled.</p>
+ */
+ final long mDisabledChangeId;
+
+ /**
+ * The required permissions to start a foreground with this type, all of them
+ * MUST have been granted.
+ */
+ final @Nullable ForegroundServiceTypePermissions mAllOfPermissions;
+
+ /**
+ * The required permissions to start a foreground with this type, any one of them
+ * being granted is sufficient.
+ */
+ final @Nullable ForegroundServiceTypePermissions mAnyOfPermissions;
+
+ /**
+ * A customized check for the permissions.
+ */
+ @Nullable ForegroundServiceTypePermission mCustomPermission;
+
+ /**
+ * Not a real change id, but a place holder.
+ */
+ private static final long INVALID_CHANGE_ID = 0L;
+
+ /**
+ * @return {@code true} if the given change id is valid.
+ */
+ private static boolean isValidChangeId(long changeId) {
+ return changeId != INVALID_CHANGE_ID;
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @hide
+ */
+ public ForegroundServiceTypePolicyInfo(@ForegroundServiceType int type,
+ long deprecationChangeId, long disabledChangeId,
+ @Nullable ForegroundServiceTypePermissions allOfPermissions,
+ @Nullable ForegroundServiceTypePermissions anyOfPermissions) {
+ mType = type;
+ mDeprecationChangeId = deprecationChangeId;
+ mDisabledChangeId = disabledChangeId;
+ mAllOfPermissions = allOfPermissions;
+ mAnyOfPermissions = anyOfPermissions;
+ }
+
+ /**
+ * @return The foreground service type.
+ */
+ @ForegroundServiceType
+ public int getForegroundServiceType() {
+ return mType;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = toPermissionString(new StringBuilder());
+ sb.append("type=0x");
+ sb.append(Integer.toHexString(mType));
+ sb.append(" deprecationChangeId=");
+ sb.append(mDeprecationChangeId);
+ sb.append(" disabledChangeId=");
+ sb.append(mDisabledChangeId);
+ sb.append(" customPermission=");
+ sb.append(mCustomPermission);
+ return sb.toString();
+ }
+
+ /**
+ * @return The required permissions.
+ */
+ public String toPermissionString() {
+ return toPermissionString(new StringBuilder()).toString();
+ }
+
+ private StringBuilder toPermissionString(StringBuilder sb) {
+ if (mAllOfPermissions != null) {
+ sb.append("all of the permissions ");
+ sb.append(mAllOfPermissions.toString());
+ sb.append(' ');
+ }
+ if (mAnyOfPermissions != null) {
+ sb.append("any of the permissions ");
+ sb.append(mAnyOfPermissions.toString());
+ sb.append(' ');
+ }
+ return sb;
+ }
+
+ /**
+ * @hide
+ */
+ public void setCustomPermission(
+ @Nullable ForegroundServiceTypePermission customPermission) {
+ mCustomPermission = customPermission;
+ }
+
+ /**
+ * @return The name of the permissions which are all required.
+ * It may contain app op names.
+ *
+ * For test only.
+ */
+ public @NonNull Optional<String[]> getRequiredAllOfPermissionsForTest() {
+ if (mAllOfPermissions == null) {
+ return Optional.empty();
+ }
+ return Optional.of(mAllOfPermissions.toStringArray());
+ }
+
+ /**
+ * @return The name of the permissions where any of the is granted is sufficient.
+ * It may contain app op names.
+ *
+ * For test only.
+ */
+ public @NonNull Optional<String[]> getRequiredAnyOfPermissionsForTest() {
+ if (mAnyOfPermissions == null) {
+ return Optional.empty();
+ }
+ return Optional.of(mAnyOfPermissions.toStringArray());
+ }
+
+ /**
+ * Whether or not this type is disabled.
+ */
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ public boolean isTypeDisabled(int callerUid) {
+ return isValidChangeId(mDisabledChangeId)
+ && CompatChanges.isChangeEnabled(mDisabledChangeId, callerUid);
+ }
+
+ /**
+ * Override the type disabling change Id.
+ *
+ * For test only.
+ */
+ public void setTypeDisabledForTest(boolean disabled, @NonNull String packageName)
+ throws RemoteException {
+ overrideChangeIdForTest(mDisabledChangeId, disabled, packageName);
+ }
+
+ /**
+ * clear the type disabling change Id.
+ *
+ * For test only.
+ */
+ public void clearTypeDisabledForTest(@NonNull String packageName) throws RemoteException {
+ clearOverrideForTest(mDisabledChangeId, packageName);
+ }
+
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ boolean isTypeDeprecated(int callerUid) {
+ return isValidChangeId(mDeprecationChangeId)
+ && CompatChanges.isChangeEnabled(mDeprecationChangeId, callerUid);
+ }
+
+ private void overrideChangeIdForTest(long changeId, boolean enable, String packageName)
+ throws RemoteException {
+ if (!isValidChangeId(changeId)) {
+ return;
+ }
+ final ArraySet<Long> enabled = new ArraySet<>();
+ final ArraySet<Long> disabled = new ArraySet<>();
+ if (enable) {
+ enabled.add(changeId);
+ } else {
+ disabled.add(changeId);
+ }
+ final CompatibilityChangeConfig overrides = new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ platformCompat.setOverridesForTest(overrides, packageName);
+ }
+
+ private void clearOverrideForTest(long changeId, @NonNull String packageName)
+ throws RemoteException {
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ platformCompat.clearOverrideForTest(changeId, packageName);
+ }
+ }
+
+ /**
+ * This represents the set of permissions that's going to be required
+ * for a specific service type.
+ *
+ * @hide
+ */
+ public static class ForegroundServiceTypePermissions {
+ /**
+ * The set of the permissions to be required.
+ */
+ final @NonNull ForegroundServiceTypePermission[] mPermissions;
+
+ /**
+ * Are we requiring all of the permissions to be granted or any of them.
+ */
+ final boolean mAllOf;
+
+ /**
+ * Constructor.
+ */
+ public ForegroundServiceTypePermissions(
+ @NonNull ForegroundServiceTypePermission[] permissions, boolean allOf) {
+ mPermissions = permissions;
+ mAllOf = allOf;
+ }
+
+ /**
+ * Check the permissions.
+ */
+ @PackageManager.PermissionResult
+ public int checkPermissions(@NonNull Context context, int callerUid, int callerPid,
+ @NonNull String packageName, boolean allowWhileInUse) {
+ if (mAllOf) {
+ for (ForegroundServiceTypePermission perm : mPermissions) {
+ final int result = perm.checkPermission(context, callerUid, callerPid,
+ packageName, allowWhileInUse);
+ if (result != PERMISSION_GRANTED) {
+ return PERMISSION_DENIED;
+ }
+ }
+ return PERMISSION_GRANTED;
+ } else {
+ boolean anyOfGranted = false;
+ for (ForegroundServiceTypePermission perm : mPermissions) {
+ final int result = perm.checkPermission(context, callerUid, callerPid,
+ packageName, allowWhileInUse);
+ if (result == PERMISSION_GRANTED) {
+ anyOfGranted = true;
+ break;
+ }
+ }
+ return anyOfGranted ? PERMISSION_GRANTED : PERMISSION_DENIED;
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("allOf=");
+ sb.append(mAllOf);
+ sb.append(' ');
+ sb.append('[');
+ for (int i = 0; i < mPermissions.length; i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(mPermissions[i].toString());
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ @NonNull String[] toStringArray() {
+ final String[] names = new String[mPermissions.length];
+ for (int i = 0; i < mPermissions.length; i++) {
+ names[i] = mPermissions[i].mName;
+ }
+ return names;
+ }
+ }
+
+ /**
+ * This represents a permission that's going to be required for a specific service type.
+ *
+ * @hide
+ */
+ public abstract static class ForegroundServiceTypePermission {
+ /**
+ * The name of this permission.
+ */
+ final @NonNull String mName;
+
+ /**
+ * Constructor.
+ */
+ public ForegroundServiceTypePermission(@NonNull String name) {
+ mName = name;
+ }
+
+ /**
+ * Check if the given uid/pid/package has the access to the permission.
+ */
+ @PackageManager.PermissionResult
+ public abstract int checkPermission(@NonNull Context context, int callerUid, int callerPid,
+ @NonNull String packageName, boolean allowWhileInUse);
+
+ @Override
+ public String toString() {
+ return mName;
+ }
+ }
+
+ /**
+ * This represents a regular Android permission to be required for a specific service type.
+ */
+ static class RegularPermission extends ForegroundServiceTypePermission {
+ RegularPermission(@NonNull String name) {
+ super(name);
+ }
+
+ @Override
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @PackageManager.PermissionResult
+ public int checkPermission(Context context, int callerUid, int callerPid,
+ String packageName, boolean allowWhileInUse) {
+ // Simple case, check if it's already granted.
+ if (context.checkPermission(mName, callerPid, callerUid) == PERMISSION_GRANTED) {
+ return PERMISSION_GRANTED;
+ }
+ if (allowWhileInUse) {
+ // Check its appops
+ final int opCode = AppOpsManager.permissionToOpCode(mName);
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ if (opCode != AppOpsManager.OP_NONE) {
+ final int currentMode = appOpsManager.unsafeCheckOpRawNoThrow(opCode, callerUid,
+ packageName);
+ if (currentMode == MODE_FOREGROUND) {
+ // It's in foreground only mode and we're allowing while-in-use.
+ return PERMISSION_GRANTED;
+ }
+ }
+ }
+ return PERMISSION_DENIED;
+ }
+ }
+
+ /**
+ * This represents an app op permission to be required for a specific service type.
+ */
+ static class AppOpPermission extends ForegroundServiceTypePermission {
+ final int mOpCode;
+
+ AppOpPermission(int opCode) {
+ super(AppOpsManager.opToPublicName(opCode));
+ mOpCode = opCode;
+ }
+
+ @Override
+ @PackageManager.PermissionResult
+ public int checkPermission(Context context, int callerUid, int callerPid,
+ String packageName, boolean allowWhileInUse) {
+ final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+ final int mode = appOpsManager.unsafeCheckOpRawNoThrow(mOpCode, callerUid, packageName);
+ return (mode == MODE_ALLOWED || (allowWhileInUse && mode == MODE_FOREGROUND))
+ ? PERMISSION_GRANTED : PERMISSION_DENIED;
+ }
+ }
+
+ /**
+ * This represents a special Android permission to be required for accessing usb devices.
+ */
+ static class UsbDevicePermission extends ForegroundServiceTypePermission {
+ UsbDevicePermission() {
+ super("USB Device");
+ }
+
+ @Override
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @PackageManager.PermissionResult
+ public int checkPermission(Context context, int callerUid, int callerPid,
+ String packageName, boolean allowWhileInUse) {
+ final UsbManager usbManager = context.getSystemService(UsbManager.class);
+ final HashMap<String, UsbDevice> devices = usbManager.getDeviceList();
+ if (!ArrayUtils.isEmpty(devices)) {
+ for (UsbDevice device : devices.values()) {
+ if (usbManager.hasPermission(device, packageName, callerPid, callerUid)) {
+ return PERMISSION_GRANTED;
+ }
+ }
+ }
+ return PERMISSION_DENIED;
+ }
+ }
+
+ /**
+ * This represents a special Android permission to be required for accessing usb accessories.
+ */
+ static class UsbAccessoryPermission extends ForegroundServiceTypePermission {
+ UsbAccessoryPermission() {
+ super("USB Accessory");
+ }
+
+ @Override
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @PackageManager.PermissionResult
+ public int checkPermission(Context context, int callerUid, int callerPid,
+ String packageName, boolean allowWhileInUse) {
+ final UsbManager usbManager = context.getSystemService(UsbManager.class);
+ final UsbAccessory[] accessories = usbManager.getAccessoryList();
+ if (!ArrayUtils.isEmpty(accessories)) {
+ for (UsbAccessory accessory: accessories) {
+ if (usbManager.hasPermission(accessory, callerPid, callerUid)) {
+ return PERMISSION_GRANTED;
+ }
+ }
+ }
+ return PERMISSION_DENIED;
+ }
+ }
+
+ /**
+ * The default policy for the foreground service types.
+ *
+ * @hide
+ */
+ public static class DefaultForegroundServiceTypePolicy extends ForegroundServiceTypePolicy {
+ private final SparseArray<ForegroundServiceTypePolicyInfo> mForegroundServiceTypePolicies =
+ new SparseArray<>();
+
+ /**
+ * Constructor
+ */
+ public DefaultForegroundServiceTypePolicy() {
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_NONE,
+ FGS_TYPE_POLICY_NONE);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_DATA_SYNC,
+ FGS_TYPE_POLICY_DATA_SYNC);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
+ FGS_TYPE_POLICY_MEDIA_PLAYBACK);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_PHONE_CALL,
+ FGS_TYPE_POLICY_PHONE_CALL);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_LOCATION,
+ FGS_TYPE_POLICY_LOCATION);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE,
+ FGS_TYPE_POLICY_CONNECTED_DEVICE);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION,
+ FGS_TYPE_POLICY_MEDIA_PROJECTION);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_CAMERA,
+ FGS_TYPE_POLICY_CAMERA);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_MICROPHONE,
+ FGS_TYPE_POLICY_MICROPHONE);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_HEALTH,
+ FGS_TYPE_POLICY_HEALTH);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING,
+ FGS_TYPE_POLICY_REMOTE_MESSAGING);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED,
+ FGS_TYPE_POLICY_SYSTEM_EXEMPTED);
+ mForegroundServiceTypePolicies.put(FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
+ FGS_TYPE_POLICY_SPECIAL_USE);
+ }
+
+ @Override
+ public ForegroundServiceTypePolicyInfo getForegroundServiceTypePolicyInfo(
+ @ForegroundServiceType int type, @ForegroundServiceType int defaultToType) {
+ ForegroundServiceTypePolicyInfo info = mForegroundServiceTypePolicies.get(type);
+ if (info == null) {
+ // Unknown type, fallback to the defaultToType
+ info = mForegroundServiceTypePolicies.get(defaultToType);
+ if (info == null) {
+ // It shouldn't happen.
+ throw new IllegalArgumentException("Invalid default fgs type " + defaultToType);
+ }
+ }
+ return info;
+ }
+
+ @Override
+ @SuppressLint("AndroidFrameworkRequiresPermission")
+ @ForegroundServicePolicyCheckCode
+ public int checkForegroundServiceTypePolicy(Context context, String packageName,
+ int callerUid, int callerPid, boolean allowWhileInUse,
+ @NonNull ForegroundServiceTypePolicyInfo policy) {
+ // Has this FGS type been disabled and not allowed to use anymore?
+ if (policy.isTypeDisabled(callerUid)) {
+ return FGS_TYPE_POLICY_CHECK_DISABLED;
+ }
+ int permissionResult = PERMISSION_DENIED;
+ // Do we have the permission to start FGS with this type.
+ if (policy.mAllOfPermissions != null) {
+ permissionResult = policy.mAllOfPermissions.checkPermissions(context,
+ callerUid, callerPid, packageName, allowWhileInUse);
+ }
+ // If it has the "all of" permissions granted, check the "any of" ones.
+ if (permissionResult == PERMISSION_GRANTED) {
+ boolean checkCustomPermission = true;
+ // Check the "any of" permissions.
+ if (policy.mAnyOfPermissions != null) {
+ permissionResult = policy.mAnyOfPermissions.checkPermissions(context,
+ callerUid, callerPid, packageName, allowWhileInUse);
+ if (permissionResult == PERMISSION_GRANTED) {
+ // We have one of them granted, no need to check custom permissions.
+ checkCustomPermission = false;
+ }
+ }
+ // If we have a customized permission checker, also call it now.
+ if (checkCustomPermission && policy.mCustomPermission != null) {
+ permissionResult = policy.mCustomPermission.checkPermission(context,
+ callerUid, callerPid, packageName, allowWhileInUse);
+ }
+ }
+ if (permissionResult != PERMISSION_GRANTED) {
+ return (CompatChanges.isChangeEnabled(
+ FGS_TYPE_PERMISSION_CHANGE_ID, callerUid))
+ ? FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED
+ : FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE;
+ }
+ // Has this FGS type been deprecated?
+ if (policy.isTypeDeprecated(callerUid)) {
+ return FGS_TYPE_POLICY_CHECK_DEPRECATED;
+ }
+ return FGS_TYPE_POLICY_CHECK_OK;
+ }
+ }
+}
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index 5388282..bd5d105 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -396,6 +396,17 @@
private final String mSuggestActionMsg;
private final String mSuggestActionMsgColumn;
+ public static final Parcelable.Creator<ActionKeyInfo> CREATOR =
+ new Parcelable.Creator<ActionKeyInfo>() {
+ public ActionKeyInfo createFromParcel(Parcel in) {
+ return new ActionKeyInfo(in);
+ }
+
+ public ActionKeyInfo[] newArray(int size) {
+ return new ActionKeyInfo[size];
+ }
+ };
+
/**
* Create one object using attributeset as input data.
* @param activityContext runtime context of the activity that the action key information
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 7635138..01e4b15 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -726,10 +727,32 @@
* for more details.
* </div>
*
+ * <div class="caution">
+ * <p><strong>Note:</strong>
+ * Beginning with SDK Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
+ * or higher are not allowed to start foreground services without specifying a valid
+ * foreground service type in the manifest attribute
+ * {@link android.R.attr#foregroundServiceType}.
+ * See
+ * <a href="{@docRoot}/about/versions/14/behavior-changes-14">
+ * Behavior changes: Apps targeting Android 14
+ * </a>
+ * for more details.
+ * </div>
+ *
* @throws ForegroundServiceStartNotAllowedException
* If the app targeting API is
* {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
* becoming foreground service due to background restriction.
+ * @throws ForegroundServiceTypeNotAllowedException
+ * If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later, and the manifest attribute
+ * {@link android.R.attr#foregroundServiceType} is not set.
+ * @throws SecurityException If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later and doesn't have the
+ * permission to start the foreground service with the specified type in the manifest attribute
+ * {@link android.R.attr#foregroundServiceType}.
*
* @param id The identifier for this notification as per
* {@link NotificationManager#notify(int, Notification)
@@ -748,51 +771,77 @@
}
}
- /**
- * An overloaded version of {@link #startForeground(int, Notification)} with additional
- * foregroundServiceType parameter.
- *
- * <p>Apps built with SDK version {@link android.os.Build.VERSION_CODES#Q} or later can specify
- * the foreground service types using attribute {@link android.R.attr#foregroundServiceType} in
- * service element of manifest file. The value of attribute
- * {@link android.R.attr#foregroundServiceType} can be multiple flags ORed together.</p>
- *
- * <p>The foregroundServiceType parameter must be a subset flags of what is specified in manifest
- * attribute {@link android.R.attr#foregroundServiceType}, if not, an IllegalArgumentException is
- * thrown. Specify foregroundServiceType parameter as
- * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST} to use all flags that
- * is specified in manifest attribute foregroundServiceType.</p>
- *
- * <div class="caution">
- * <p><strong>Note:</strong>
- * Beginning with SDK Version {@link android.os.Build.VERSION_CODES#S},
- * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#S}
- * or higher are not allowed to start foreground services from the background.
- * See
- * <a href="{@docRoot}/about/versions/12/behavior-changes-12">
- * Behavior changes: Apps targeting Android 12
- * </a>
- * for more details.
- * </div>
- *
- * @param id The identifier for this notification as per
- * {@link NotificationManager#notify(int, Notification)
- * NotificationManager.notify(int, Notification)}; must not be 0.
- * @param notification The Notification to be displayed.
- * @param foregroundServiceType must be a subset flags of manifest attribute
- * {@link android.R.attr#foregroundServiceType} flags.
- *
- * @throws IllegalArgumentException if param foregroundServiceType is not subset of manifest
- * attribute {@link android.R.attr#foregroundServiceType}.
- * @throws ForegroundServiceStartNotAllowedException
- * If the app targeting API is
- * {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
- * becoming foreground service due to background restriction.
- *
- * @see android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST
- */
+ /**
+ * An overloaded version of {@link #startForeground(int, Notification)} with additional
+ * foregroundServiceType parameter.
+ *
+ * <p>Apps built with SDK version {@link android.os.Build.VERSION_CODES#Q} or later can specify
+ * the foreground service types using attribute {@link android.R.attr#foregroundServiceType} in
+ * service element of manifest file. The value of attribute
+ * {@link android.R.attr#foregroundServiceType} can be multiple flags ORed together.</p>
+ *
+ * <p>The foregroundServiceType parameter must be a subset flags of what is specified in
+ * manifest attribute {@link android.R.attr#foregroundServiceType}, if not, an
+ * IllegalArgumentException is thrown. Specify foregroundServiceType parameter as
+ * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST} to use all flags that
+ * is specified in manifest attribute foregroundServiceType.</p>
+ *
+ * <div class="caution">
+ * <p><strong>Note:</strong>
+ * Beginning with SDK Version {@link android.os.Build.VERSION_CODES#S},
+ * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#S}
+ * or higher are not allowed to start foreground services from the background.
+ * See
+ * <a href="{@docRoot}/about/versions/12/behavior-changes-12">
+ * Behavior changes: Apps targeting Android 12
+ * </a>
+ * for more details.
+ * </div>
+ *
+ * <div class="caution">
+ * <p><strong>Note:</strong>
+ * Beginning with SDK Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * apps targeting SDK Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
+ * or higher are not allowed to start foreground services without specifying a valid
+ * foreground service type in the manifest attribute
+ * {@link android.R.attr#foregroundServiceType}, and the parameter {@code foregroundServiceType}
+ * here must not be the {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ * See
+ * <a href="{@docRoot}/about/versions/14/behavior-changes-14">
+ * Behavior changes: Apps targeting Android 14
+ * </a>
+ * for more details.
+ * </div>
+ *
+ * @param id The identifier for this notification as per
+ * {@link NotificationManager#notify(int, Notification)
+ * NotificationManager.notify(int, Notification)}; must not be 0.
+ * @param notification The Notification to be displayed.
+ * @param foregroundServiceType must be a subset flags of manifest attribute
+ * {@link android.R.attr#foregroundServiceType} flags; must not be
+ * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ *
+ * @throws IllegalArgumentException if param foregroundServiceType is not subset of manifest
+ * attribute {@link android.R.attr#foregroundServiceType}.
+ * @throws ForegroundServiceStartNotAllowedException
+ * If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#S} or later, and the service is restricted from
+ * becoming foreground service due to background restriction.
+ * @throws ForegroundServiceTypeNotAllowedException
+ * If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later, and the manifest attribute
+ * {@link android.R.attr#foregroundServiceType} is not set, or the param
+ * {@code foregroundServiceType} is {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_NONE}.
+ * @throws SecurityException If the app targeting API is
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or later and doesn't have the
+ * permission to start the foreground service with the specified type in
+ * {@code foregroundServiceType}.
+ * {@link android.R.attr#foregroundServiceType}.
+ *
+ * @see android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MANIFEST
+ */
public final void startForeground(int id, @NonNull Notification notification,
- @ForegroundServiceType int foregroundServiceType) {
+ @RequiresPermission @ForegroundServiceType int foregroundServiceType) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, id,
diff --git a/core/java/android/content/ActivityNotFoundException.java b/core/java/android/content/ActivityNotFoundException.java
index 16149bb..5b50189 100644
--- a/core/java/android/content/ActivityNotFoundException.java
+++ b/core/java/android/content/ActivityNotFoundException.java
@@ -31,5 +31,4 @@
{
super(name);
}
-};
-
+}
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
index f888813..1b5f64c 100644
--- a/core/java/android/content/integrity/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -261,8 +261,8 @@
}
LongAtomicFormula that = (LongAtomicFormula) o;
return getKey() == that.getKey()
- && mValue == that.mValue
- && mOperator == that.mOperator;
+ && Objects.equals(mValue, that.mValue)
+ && Objects.equals(mOperator, that.mOperator);
}
@Override
@@ -628,7 +628,7 @@
return false;
}
BooleanAtomicFormula that = (BooleanAtomicFormula) o;
- return getKey() == that.getKey() && mValue == that.mValue;
+ return getKey() == that.getKey() && Objects.equals(mValue, that.mValue);
}
@Override
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index dc6a8c9..6c1d84b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -165,6 +165,21 @@
"android.internal.PROPERTY_NO_APP_DATA_STORAGE";
/**
+ * <service> level {@link android.content.pm.PackageManager.Property} tag specifying
+ * the actual use case of the service if it's foreground service with the type
+ * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE}.
+ *
+ * <p>
+ * For example:
+ * <service>
+ * <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
+ * android:value="foo"/>
+ * </service>
+ */
+ public static final String PROPERTY_SPECIAL_USE_FGS_SUBTYPE =
+ "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
+
+ /**
* A property value set within the manifest.
* <p>
* The value of a property will only have a single type, as defined by
@@ -189,12 +204,12 @@
@VisibleForTesting
public Property(@NonNull String name, int type,
@NonNull String packageName, @Nullable String className) {
- assert name != null;
- assert type >= TYPE_BOOLEAN && type <= TYPE_STRING;
- assert packageName != null;
- this.mName = name;
+ if (type < TYPE_BOOLEAN || type > TYPE_STRING) {
+ throw new IllegalArgumentException("Invalid type");
+ }
+ this.mName = Objects.requireNonNull(name);
this.mType = type;
- this.mPackageName = packageName;
+ this.mPackageName = Objects.requireNonNull(packageName);
this.mClassName = className;
}
/** @hide */
@@ -442,9 +457,8 @@
*/
public ComponentEnabledSetting(@NonNull ComponentName componentName,
@EnabledState int newState, @EnabledFlags int flags) {
- Objects.nonNull(componentName);
mPackageName = null;
- mComponentName = componentName;
+ mComponentName = Objects.requireNonNull(componentName);
mEnabledState = newState;
mEnabledFlags = flags;
}
@@ -460,8 +474,7 @@
*/
public ComponentEnabledSetting(@NonNull String packageName,
@EnabledState int newState, @EnabledFlags int flags) {
- Objects.nonNull(packageName);
- mPackageName = packageName;
+ mPackageName = Objects.requireNonNull(packageName);
mComponentName = null;
mEnabledState = newState;
mEnabledFlags = flags;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 88d7004..ab20b6f 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -16,7 +16,9 @@
package android.content.pm;
+import android.Manifest;
import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Printer;
@@ -100,7 +102,15 @@
/**
* The default foreground service type if not been set in manifest file.
+ *
+ * <p>Apps targeting API level {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and
+ * later should NOT use this type,
+ * calling {@link android.app.Service#startForeground(int, android.app.Notification, int)} with
+ * this type will get a {@link android.app.ForegroundServiceTypeNotAllowedException}.</p>
+ *
+ * @deprecated Do not use.
*/
+ @Deprecated
public static final int FOREGROUND_SERVICE_TYPE_NONE = 0;
/**
@@ -108,14 +118,36 @@
* the {@link android.R.attr#foregroundServiceType} attribute.
* Data(photo, file, account) upload/download, backup/restore, import/export, fetch,
* transfer over network between device and cloud.
+ *
+ * <p>Apps targeting API level {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and
+ * later should NOT use this type:
+ * calling {@link android.app.Service#startForeground(int, android.app.Notification, int)} with
+ * this type on devices running {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} is still
+ * allowed, but calling it with this type on devices running future platform releases may get a
+ * {@link android.app.ForegroundServiceTypeNotAllowedException}.</p>
+ *
+ * @deprecated Use {@link android.app.job.JobInfo.Builder} data transfer APIs instead.
*/
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC,
+ conditional = true
+ )
+ @Deprecated
public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1 << 0;
/**
* Constant corresponding to <code>mediaPlayback</code> in
* the {@link android.R.attr#foregroundServiceType} attribute.
* Music, video, news or other media playback.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PLAYBACK}.
*/
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK,
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK = 1 << 1;
/**
@@ -123,28 +155,94 @@
* the {@link android.R.attr#foregroundServiceType} attribute.
* Ongoing operations related to phone calls, video conferencing,
* or similar interactive communication.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_PHONE_CALL} and
+ * {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
*/
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_PHONE_CALL,
+ },
+ anyOf = {
+ Manifest.permission.MANAGE_OWN_CALLS,
+ },
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_PHONE_CALL = 1 << 2;
/**
* Constant corresponding to <code>location</code> in
* the {@link android.R.attr#foregroundServiceType} attribute.
* GPS, map, navigation location update.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_LOCATION} and one of the
+ * following permissions:
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION},
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
*/
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_LOCATION,
+ },
+ anyOf = {
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ },
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 1 << 3;
/**
* Constant corresponding to <code>connectedDevice</code> in
* the {@link android.R.attr#foregroundServiceType} attribute.
* Auto, bluetooth, TV or other devices connection, monitoring and interaction.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_CONNECTED_DEVICE} and one of the
+ * following permissions:
+ * {@link android.Manifest.permission#BLUETOOTH_CONNECT},
+ * {@link android.Manifest.permission#CHANGE_NETWORK_STATE},
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE},
+ * {@link android.Manifest.permission#CHANGE_WIFI_MULTICAST_STATE},
+ * {@link android.Manifest.permission#NFC},
+ * {@link android.Manifest.permission#TRANSMIT_IR},
+ * or has been granted the access to one of the attached USB devices/accessories.
*/
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE,
+ },
+ anyOf = {
+ Manifest.permission.BLUETOOTH_CONNECT,
+ Manifest.permission.CHANGE_NETWORK_STATE,
+ Manifest.permission.CHANGE_WIFI_STATE,
+ Manifest.permission.CHANGE_WIFI_MULTICAST_STATE,
+ Manifest.permission.NFC,
+ Manifest.permission.TRANSMIT_IR,
+ },
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 1 << 4;
/**
* Constant corresponding to {@code mediaProjection} in
* the {@link android.R.attr#foregroundServiceType} attribute.
* Managing a media projection session, e.g for screen recording or taking screenshots.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PROJECTION}, and the user must
+ * have allowed the screen capture request from this app.
*/
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION,
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION = 1 << 5;
/**
@@ -155,7 +253,21 @@
* above, a foreground service will not be able to access the camera if this type is not
* specified in the manifest and in
* {@link android.app.Service#startForeground(int, android.app.Notification, int)}.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_CAMERA} and
+ * {@link android.Manifest.permission#CAMERA}.
*/
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_CAMERA,
+ },
+ anyOf = {
+ Manifest.permission.CAMERA,
+ },
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 1 << 6;
/**
@@ -166,17 +278,148 @@
* above, a foreground service will not be able to access the microphone if this type is not
* specified in the manifest and in
* {@link android.app.Service#startForeground(int, android.app.Notification, int)}.
+ *
+ * <p>Starting foreground service with this type from apps targeting API level
+ * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and later, will require permission
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_MICROPHONE} and one of the following
+ * permissions:
+ * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT},
+ * {@link android.Manifest.permission#RECORD_AUDIO}.
*/
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_MICROPHONE,
+ },
+ anyOf = {
+ Manifest.permission.CAPTURE_AUDIO_OUTPUT,
+ Manifest.permission.RECORD_AUDIO,
+ },
+ conditional = true
+ )
public static final int FOREGROUND_SERVICE_TYPE_MICROPHONE = 1 << 7;
/**
- * The number of foreground service types, this doesn't include
- * the {@link #FOREGROUND_SERVICE_TYPE_MANIFEST} and {@link #FOREGROUND_SERVICE_TYPE_NONE}
- * as they're not real service types.
+ * Constant corresponding to {@code health} in
+ * the {@link android.R.attr#foregroundServiceType} attribute.
+ * Health, wellness and fitness.
+ *
+ * <p>The caller app is required to have the permissions
+ * {@link android.Manifest.permission#FOREGROUND_SERVICE_HEALTH} and one of the following
+ * permissions:
+ * {@link android.Manifest.permission#ACTIVITY_RECOGNITION},
+ * {@link android.Manifest.permission#BODY_SENSORS},
+ * {@link android.Manifest.permission#HIGH_SAMPLING_RATE_SENSORS}.
+ */
+ @RequiresPermission(
+ allOf = {
+ Manifest.permission.FOREGROUND_SERVICE_HEALTH,
+ },
+ anyOf = {
+ Manifest.permission.ACTIVITY_RECOGNITION,
+ Manifest.permission.BODY_SENSORS,
+ Manifest.permission.HIGH_SAMPLING_RATE_SENSORS,
+ },
+ conditional = true
+ )
+ public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 1 << 8;
+
+ /**
+ * Constant corresponding to {@code remoteMessaging} in
+ * the {@link android.R.attr#foregroundServiceType} attribute.
+ * Messaging use cases which host local server to relay messages across devices.
+ */
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING,
+ conditional = true
+ )
+ public static final int FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING = 1 << 9;
+
+ /**
+ * Constant corresponding to {@code systemExempted} in
+ * the {@link android.R.attr#foregroundServiceType} attribute.
+ * The system exmpted foreground service use cases.
+ *
+ * <p class="note">Note, apps are allowed to use this type only in the following cases:
+ * <ul>
+ * <li>App has a UID < {@link android.os.Process#FIRST_APPLICATION_UID}</li>
+ * <li>App is on Doze allowlist</li>
+ * <li>Device is running in <a href="https://android.googlesource.com/platform/frameworks/base/+/master/packages/SystemUI/docs/demo_mode.md">Demo Mode</a></li>
+ * <li><a href="https://source.android.com/devices/tech/admin/provision">Device owner app</a><li>
+ * <li><a href="https://source.android.com/devices/tech/admin/managed-profiles">Profile owner apps</a><li>
+ * <li>Persistent apps</li>
+ * <li><a href="https://source.android.com/docs/core/connect/carrier">Carrier privileged apps</a></li>
+ * <li>Apps that have the {@code android.app.role.RoleManager#ROLE_EMERGENCY} role</li>
+ * <li>Headless system apps</li>
+ * <li><a href="{@docRoot}guide/topics/admin/device-admin">Device admin apps</a></li>
+ * <li>Active VPN apps</li>
+ * <li>Apps holding {@link Manifest.permission#SCHEDULE_EXACT_ALARM} or
+ * {@link Manifest.permission#USE_EXACT_ALARM} permission.</li>
+ * </ul>
+ * </p>
+ */
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED,
+ conditional = true
+ )
+ public static final int FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED = 1 << 10;
+
+ /**
+ * Constant corresponding to {@code specialUse} in
+ * the {@link android.R.attr#foregroundServiceType} attribute.
+ * Use cases that can't be categorized into any other foreground service types, but also
+ * can't use {@link android.app.job.JobInfo.Builder} APIs.
+ *
+ * <p>The use of this foreground service type may be restricted. Additionally, apps must declare
+ * a service-level {@link PackageManager#PROPERTY_SPECIAL_USE_FGS_SUBTYPE <property>} in
+ * {@code AndroidManifest.xml} as a hint of what the exact use case here is.
+ * Here is an example:
+ * <pre>
+ * <uses-permission
+ * android:name="android.permissions.FOREGROUND_SERVICE_SPECIAL_USE"
+ * />
+ * <service
+ * android:name=".MySpecialForegroundService"
+ * android:foregroundServiceType="specialUse">
+ * <property
+ * android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
+ * android:value="foo"
+ * />
+ * </service>
+ * </pre>
+ *
+ * In a future release of Android, if the above foreground service type {@code foo} is supported
+ * by the platform, to offer the backward compatibility, the app could specify
+ * the {@code android:maxSdkVersion} attribute in the <uses-permission> section,
+ * and also add the foreground service type {@code foo} into
+ * the {@code android:foregroundServiceType}, therefore the same app could be installed
+ * in both platforms.
+ * <pre>
+ * <uses-permission
+ * android:name="android.permissions.FOREGROUND_SERVICE_SPECIAL_USE"
+ * android:maxSdkVersion="last_sdk_version_without_type_foo"
+ * />
+ * <service
+ * android:name=".MySpecialForegroundService"
+ * android:foregroundServiceType="specialUse|foo">
+ * <property
+ * android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE""
+ * android:value="foo"
+ * />
+ * </service>
+ * </pre>
+ */
+ @RequiresPermission(
+ value = Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE,
+ conditional = true
+ )
+ public static final int FOREGROUND_SERVICE_TYPE_SPECIAL_USE = 1 << 30;
+
+ /**
+ * The max index being used in the definition of foreground service types.
*
* @hide
*/
- public static final int NUM_OF_FOREGROUND_SERVICE_TYPES = 8;
+ public static final int FOREGROUND_SERVICE_TYPES_MAX_INDEX = 30;
/**
* A special value indicates to use all types set in manifest file.
@@ -199,7 +442,11 @@
FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE,
FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION,
FOREGROUND_SERVICE_TYPE_CAMERA,
- FOREGROUND_SERVICE_TYPE_MICROPHONE
+ FOREGROUND_SERVICE_TYPE_MICROPHONE,
+ FOREGROUND_SERVICE_TYPE_HEALTH,
+ FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING,
+ FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED,
+ FOREGROUND_SERVICE_TYPE_SPECIAL_USE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ForegroundServiceType {}
@@ -275,6 +522,14 @@
return "camera";
case FOREGROUND_SERVICE_TYPE_MICROPHONE:
return "microphone";
+ case FOREGROUND_SERVICE_TYPE_HEALTH:
+ return "health";
+ case FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING:
+ return "remoteMessaging";
+ case FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED:
+ return "systemExempted";
+ case FOREGROUND_SERVICE_TYPE_SPECIAL_USE:
+ return "specialUse";
default:
return "unknown";
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 1f83d75..295df5c 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -50,6 +50,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import java.lang.IllegalArgumentException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -1360,7 +1361,9 @@
@NonNull
public Builder setIntents(@NonNull Intent[] intents) {
Objects.requireNonNull(intents, "intents cannot be null");
- Objects.requireNonNull(intents.length, "intents cannot be empty");
+ if (intents.length == 0) {
+ throw new IllegalArgumentException("intents cannot be empty");
+ }
for (Intent intent : intents) {
Objects.requireNonNull(intent, "intents cannot contain null");
Objects.requireNonNull(intent.getAction(), "intent's action must be set");
@@ -1398,7 +1401,9 @@
@NonNull
public Builder setPersons(@NonNull Person[] persons) {
Objects.requireNonNull(persons, "persons cannot be null");
- Objects.requireNonNull(persons.length, "persons cannot be empty");
+ if (persons.length == 0) {
+ throw new IllegalArgumentException("persons cannot be empty");
+ }
for (Person person : persons) {
Objects.requireNonNull(person, "persons cannot contain null");
}
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 9baa6ba..2be0323 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -159,6 +159,18 @@
public static final int FLAG_EPHEMERAL_ON_CREATE = 0x00002000;
/**
+ * Indicates that this user is the designated main user on the device. This user may have access
+ * to certain features which are limited to at most one user.
+ *
+ * <p>Currently, this will be the first user to go through setup on the device, but in future
+ * releases this status may be transferable or may even not be given to any users.
+ *
+ * <p>This is not necessarily the system user. For example, it will not be the system user on
+ * devices for which {@link UserManager#isHeadlessSystemUserMode()} returns true.
+ */
+ public static final int FLAG_MAIN = 0x00004000;
+
+ /**
* @hide
*/
@IntDef(flag = true, prefix = "FLAG_", value = {
@@ -175,7 +187,8 @@
FLAG_FULL,
FLAG_SYSTEM,
FLAG_PROFILE,
- FLAG_EPHEMERAL_ON_CREATE
+ FLAG_EPHEMERAL_ON_CREATE,
+ FLAG_MAIN
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserInfoFlag {
@@ -369,6 +382,13 @@
}
/**
+ * @see #FLAG_MAIN
+ */
+ public boolean isMain() {
+ return (flags & FLAG_MAIN) == FLAG_MAIN;
+ }
+
+ /**
* Returns true if the user is a split system user.
* <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
* the method always returns false.
diff --git a/core/java/android/hardware/CameraInfo.java b/core/java/android/hardware/CameraInfo.java
index 072be50..41ef6aa 100644
--- a/core/java/android/hardware/CameraInfo.java
+++ b/core/java/android/hardware/CameraInfo.java
@@ -60,4 +60,4 @@
return new CameraInfo[size];
}
};
-};
+}
diff --git a/core/java/android/hardware/CameraStatus.java b/core/java/android/hardware/CameraStatus.java
index 874af29..fa35efb 100644
--- a/core/java/android/hardware/CameraStatus.java
+++ b/core/java/android/hardware/CameraStatus.java
@@ -68,4 +68,4 @@
return new CameraStatus[size];
}
};
-};
+}
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index d415706..267ef36 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -118,4 +118,4 @@
}
return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto);
}
-};
+}
diff --git a/core/java/android/hardware/camera2/impl/FrameNumberTracker.java b/core/java/android/hardware/camera2/impl/FrameNumberTracker.java
index 7b6a457..8304796 100644
--- a/core/java/android/hardware/camera2/impl/FrameNumberTracker.java
+++ b/core/java/android/hardware/camera2/impl/FrameNumberTracker.java
@@ -26,6 +26,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.TreeMap;
/**
@@ -63,11 +64,11 @@
}
private void update() {
- Iterator iter = mFutureErrorMap.entrySet().iterator();
+ Iterator<Map.Entry<Long, Integer>> iter = mFutureErrorMap.entrySet().iterator();
while (iter.hasNext()) {
- TreeMap.Entry pair = (TreeMap.Entry)iter.next();
- Long errorFrameNumber = (Long)pair.getKey();
- int requestType = (int) pair.getValue();
+ Map.Entry<Long, Integer> pair = iter.next();
+ long errorFrameNumber = pair.getKey();
+ int requestType = pair.getValue();
Boolean removeError = false;
if (errorFrameNumber == mCompletedFrameNumber[requestType] + 1) {
removeError = true;
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableEnum.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableEnum.java
index 621a418..92a2fb6 100644
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableEnum.java
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableEnum.java
@@ -103,6 +103,7 @@
return new MarshalerEnum(managedType, nativeType);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public boolean isTypeMappingSupported(TypeReference<T> managedType, int nativeType) {
if (nativeType == TYPE_INT32 || nativeType == TYPE_BYTE) {
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index a0d8f8d..f4b87b9 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -1344,7 +1344,8 @@
return false;
}
for (int j = 0; j < mSensorPixelModesUsed.size(); j++) {
- if (mSensorPixelModesUsed.get(j) != other.mSensorPixelModesUsed.get(j)) {
+ if (!Objects.equals(
+ mSensorPixelModesUsed.get(j), other.mSensorPixelModesUsed.get(j))) {
return false;
}
}
diff --git a/core/java/android/hardware/fingerprint/Fingerprint.java b/core/java/android/hardware/fingerprint/Fingerprint.java
index 9ce834ca..c01c94c 100644
--- a/core/java/android/hardware/fingerprint/Fingerprint.java
+++ b/core/java/android/hardware/fingerprint/Fingerprint.java
@@ -69,4 +69,4 @@
return new Fingerprint[size];
}
};
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
index f8e2558..d4b76c8 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -53,8 +53,8 @@
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -89,12 +89,10 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Prefix {}
- private static final HashMap<String, String> sPrefixLegacyFileNameMap =
- new HashMap<String, String>() {{
- put(PREFIX_XT, "netstats_xt.bin");
- put(PREFIX_UID, "netstats_uid.bin");
- put(PREFIX_UID_TAG, "netstats_uid.bin");
- }};
+ private static final Map<String, String> sPrefixLegacyFileNameMap = Map.of(
+ PREFIX_XT, "netstats_xt.bin",
+ PREFIX_UID, "netstats_uid.bin",
+ PREFIX_UID_TAG, "netstats_uid.bin");
// These version constants are copied from NetworkStatsCollection/History, which is okay for
// OEMs to modify to adapt their own logic.
diff --git a/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
index 4bc5b49..0427742 100644
--- a/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
@@ -53,7 +53,7 @@
if (in.keySet().size() != EXPECTED_BUNDLE_KEY_CNT) {
throw new IllegalArgumentException(
String.format(
- "Expect PersistableBundle to have %d element but found: %d",
+ "Expect PersistableBundle to have %d element but found: %s",
EXPECTED_BUNDLE_KEY_CNT, in.keySet()));
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index fbfe548..1f21bfe 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2341,12 +2341,18 @@
}
/**
- * Used to check if the context user is the primary user. The primary user
- * is the first human user on a device. This is not supported in headless system user mode.
+ * Used to check if the context user is the primary user. The primary user is the first human
+ * user on a device. This is not supported in headless system user mode.
*
* @return whether the context user is the primary user.
+ *
+ * @deprecated This method always returns true for the system user, who may not be a full user
+ * if {@link #isHeadlessSystemUserMode} is true. Use {@link #isSystemUser}, {@link #isAdminUser}
+ * or {@link #isMainUser} instead.
+ *
* @hide
*/
+ @Deprecated
@SystemApi
@RequiresPermission(anyOf = {
Manifest.permission.MANAGE_USERS,
@@ -2371,6 +2377,29 @@
}
/**
+ * Returns true if the context user is the designated "main user" of the device. This user may
+ * have access to certain features which are limited to at most one user.
+ *
+ * <p>Currently, the first human user on the device will be the main user; in the future, the
+ * concept may be transferable, so a different user (or even no user at all) may be designated
+ * the main user instead.
+ *
+ * <p>Note that this will be the not be the system user on devices for which
+ * {@link #isHeadlessSystemUserMode()} returns true.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS,
+ Manifest.permission.QUERY_USERS})
+ @UserHandleAware
+ public boolean isMainUser() {
+ final UserInfo user = getUserInfo(mUserId);
+ return user != null && user.isMain();
+ }
+
+ /**
* Used to check if the context user is an admin user. An admin user is allowed to
* modify or configure certain settings that aren't available to non-admin users,
* create and delete additional users, etc. There can be more than one admin users.
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index 2c382ef..c78fb1a 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -61,4 +61,4 @@
out.writeInt(resultCode);
out.writeByteArray(exportData);
}
-};
+}
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index aa45c20..6e8198b 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -49,6 +49,17 @@
mShowComplications = shouldShowComplications;
onStartDream(layoutParams);
}
+
+ @Override
+ public void wakeUp() {
+ onWakeUp(() -> {
+ try {
+ mDreamOverlayCallback.onWakeUpComplete();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not notify dream of wakeUp:" + e);
+ }
+ });
+ }
};
IDreamOverlayCallback mDreamOverlayCallback;
@@ -71,6 +82,17 @@
public abstract void onStartDream(@NonNull WindowManager.LayoutParams layoutParams);
/**
+ * This method is overridden by implementations to handle when the dream has been requested
+ * to wakeup. This allows any overlay animations to run.
+ *
+ * @param onCompleteCallback The callback to trigger to notify the dream service that the
+ * overlay has completed waking up.
+ * @hide
+ */
+ public void onWakeUp(@NonNull Runnable onCompleteCallback) {
+ }
+
+ /**
* This method is invoked to request the dream exit.
*/
public final void requestExit() {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index bb22920..8b9852a 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -312,7 +312,14 @@
@Override
public void onExitRequested() {
// Simply finish dream when exit is requested.
- finish();
+ mHandler.post(() -> finish());
+ }
+
+ @Override
+ public void onWakeUpComplete() {
+ // Finish the dream once overlay animations are complete. Execute on handler since
+ // this is coming in on the overlay binder.
+ mHandler.post(() -> finish());
}
};
@@ -975,7 +982,18 @@
* </p>
*/
public void onWakeUp() {
- finish();
+ if (mOverlayConnection != null) {
+ mOverlayConnection.addConsumer(overlay -> {
+ try {
+ overlay.wakeUp();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error waking the overlay service", e);
+ finish();
+ }
+ });
+ } else {
+ finish();
+ }
}
/** {@inheritDoc} */
diff --git a/core/java/android/service/dreams/IDreamOverlay.aidl b/core/java/android/service/dreams/IDreamOverlay.aidl
index 05ebbfe..7aeceb2c 100644
--- a/core/java/android/service/dreams/IDreamOverlay.aidl
+++ b/core/java/android/service/dreams/IDreamOverlay.aidl
@@ -38,4 +38,7 @@
*/
void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
in String dreamComponent, in boolean shouldShowComplications);
+
+ /** Called when the dream is waking, to do any exit animations */
+ void wakeUp();
}
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index ec76a33..4ad63f1 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -28,4 +28,7 @@
* Invoked to request the dream exit.
*/
void onExitRequested();
+
+ /** Invoked when the dream overlay wakeUp animation is complete. */
+ void onWakeUpComplete();
}
\ No newline at end of file
diff --git a/core/java/android/text/style/AccessibilityURLSpan.java b/core/java/android/text/style/AccessibilityURLSpan.java
index bd81623..e280bdf 100644
--- a/core/java/android/text/style/AccessibilityURLSpan.java
+++ b/core/java/android/text/style/AccessibilityURLSpan.java
@@ -26,6 +26,7 @@
* It is used to replace URLSpans in {@link AccessibilityNodeInfo#setText(CharSequence)}
* @hide
*/
+@SuppressWarnings("ParcelableCreator")
public class AccessibilityURLSpan extends URLSpan implements Parcelable {
final AccessibilityClickableSpan mAccessibilityClickableSpan;
diff --git a/core/java/android/util/AndroidException.java b/core/java/android/util/AndroidException.java
index 1345ddf..d1b9d9f 100644
--- a/core/java/android/util/AndroidException.java
+++ b/core/java/android/util/AndroidException.java
@@ -40,5 +40,5 @@
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
-};
+}
diff --git a/core/java/android/util/AndroidRuntimeException.java b/core/java/android/util/AndroidRuntimeException.java
index 2b824bf..72c34d8b 100644
--- a/core/java/android/util/AndroidRuntimeException.java
+++ b/core/java/android/util/AndroidRuntimeException.java
@@ -34,5 +34,4 @@
public AndroidRuntimeException(Exception cause) {
super(cause);
}
-};
-
+}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 7b6a6d2..4afd268 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -132,6 +132,12 @@
*/
public static final String SETTINGS_ADB_METRICS_WRITER = "settings_adb_metrics_writer";
+ /**
+ * Flag to enable/disable biometrics enrollment v2
+ * @hide
+ */
+ public static final String SETTINGS_BIOMETRICS2_ENROLLMENT = "settings_biometrics2_enrollment";
+
private static final Map<String, String> DEFAULT_FLAGS;
static {
@@ -167,6 +173,7 @@
DEFAULT_FLAGS.put(SETTINGS_NEW_KEYBOARD_TRACKPAD, "false");
DEFAULT_FLAGS.put(SETTINGS_ENABLE_SPA, "false");
DEFAULT_FLAGS.put(SETTINGS_ADB_METRICS_WRITER, "false");
+ DEFAULT_FLAGS.put(SETTINGS_BIOMETRICS2_ENROLLMENT, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
index 9fd0ab9..41c171a 100644
--- a/core/java/android/util/Range.java
+++ b/core/java/android/util/Range.java
@@ -356,4 +356,4 @@
private final T mLower;
private final T mUpper;
-};
+}
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 19de396..44318bb 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -696,5 +696,5 @@
sb.append("}");
return sb.toString();
}
-};
+}
diff --git a/core/java/android/view/CutoutSpecification.java b/core/java/android/view/CutoutSpecification.java
index f8aa934..3fc3b6a 100644
--- a/core/java/android/view/CutoutSpecification.java
+++ b/core/java/android/view/CutoutSpecification.java
@@ -394,7 +394,6 @@
Log.e(TAG, "According to SVG definition, it shouldn't happen");
return;
}
- spec.trim();
translateMatrix();
final Path newPath = PathParser.createPathFromPathData(spec);
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index ea97995..ff282ba 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.app.WindowConfiguration.ActivityType;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
@@ -157,7 +158,7 @@
}
}
- public static final @android.annotation.NonNull Creator<RemoteAnimationDefinition> CREATOR =
+ public static final @NonNull Creator<RemoteAnimationDefinition> CREATOR =
new Creator<RemoteAnimationDefinition>() {
public RemoteAnimationDefinition createFromParcel(Parcel in) {
return new RemoteAnimationDefinition(in);
@@ -199,18 +200,17 @@
return 0;
}
- private static final @android.annotation.NonNull Creator<RemoteAnimationAdapterEntry> CREATOR
- = new Creator<RemoteAnimationAdapterEntry>() {
+ public static final @NonNull Parcelable.Creator<RemoteAnimationAdapterEntry> CREATOR =
+ new Parcelable.Creator<RemoteAnimationAdapterEntry>() {
+ @Override
+ public RemoteAnimationAdapterEntry createFromParcel(Parcel in) {
+ return new RemoteAnimationAdapterEntry(in);
+ }
- @Override
- public RemoteAnimationAdapterEntry createFromParcel(Parcel in) {
- return new RemoteAnimationAdapterEntry(in);
- }
-
- @Override
- public RemoteAnimationAdapterEntry[] newArray(int size) {
- return new RemoteAnimationAdapterEntry[size];
- }
- };
+ @Override
+ public RemoteAnimationAdapterEntry[] newArray(int size) {
+ return new RemoteAnimationAdapterEntry[size];
+ }
+ };
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index cc85181..16f6cea 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3408,6 +3408,11 @@
* alt="Screenshot of an activity on a display with a cutout on the long edge in portrait,
* letterbox is applied."/>
*
+ * <p>
+ * Note: Android might not allow the content view to overlap the system bars in view level.
+ * To override this behavior and allow content to be able to extend into the cutout area,
+ * call {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
+ *
* @see DisplayCutout
* @see WindowInsets#getDisplayCutout()
* @see #layoutInDisplayCutoutMode
@@ -3443,6 +3448,11 @@
* In this mode, the window extends under cutouts on the all edges of the display in both
* portrait and landscape, regardless of whether the window is hiding the system bars.
*
+ * <p>
+ * Note: Android might not allow the content view to overlap the system bars in view level.
+ * To override this behavior and allow content to be able to extend into the cutout area,
+ * call {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
+ *
* @see DisplayCutout
* @see WindowInsets#getDisplayCutout()
* @see #layoutInDisplayCutoutMode
diff --git a/core/java/android/webkit/ConsoleMessage.java b/core/java/android/webkit/ConsoleMessage.java
index 5474557..89cb6b2 100644
--- a/core/java/android/webkit/ConsoleMessage.java
+++ b/core/java/android/webkit/ConsoleMessage.java
@@ -68,4 +68,4 @@
public int lineNumber() {
return mLineNumber;
}
-};
+}
diff --git a/core/java/android/webkit/ValueCallback.java b/core/java/android/webkit/ValueCallback.java
index 5c7d97f..3d5bb49 100644
--- a/core/java/android/webkit/ValueCallback.java
+++ b/core/java/android/webkit/ValueCallback.java
@@ -25,4 +25,4 @@
* @param value The value.
*/
public void onReceiveValue(T value);
-};
+}
diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java
index db15145..e62d5c9 100644
--- a/core/java/android/window/TransitionFilter.java
+++ b/core/java/android/window/TransitionFilter.java
@@ -296,7 +296,7 @@
out.append((i == 0 ? "" : ",") + TransitionInfo.modeToString(mModes[i]));
}
}
- out.append("]").toString();
+ out.append("]");
out.append(" flags=" + TransitionInfo.flagsToString(mFlags));
out.append(" mustBeTask=" + mMustBeTask);
out.append(" order=" + containerOrderToString(mOrder));
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 30da4b4..88447da 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -58,11 +58,12 @@
SyncNotedAppOp noteProxyOperation(int code, in AttributionSource attributionSource,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation);
- SyncNotedAppOp startProxyOperation(int code, in AttributionSource attributionSource,
- boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
- boolean shouldCollectMessage, boolean skipProxyOperation, int proxyAttributionFlags,
- int proxiedAttributionFlags, int attributionChainId);
- void finishProxyOperation(int code, in AttributionSource attributionSource,
+ SyncNotedAppOp startProxyOperation(IBinder clientId, int code,
+ in AttributionSource attributionSource, boolean startIfModeDefault,
+ boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
+ boolean skipProxyOperation, int proxyAttributionFlags, int proxiedAttributionFlags,
+ int attributionChainId);
+ void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource,
boolean skipProxyOperation);
// Remaining methods are only used in Java.
diff --git a/core/java/com/android/internal/app/procstats/AssociationState.java b/core/java/com/android/internal/app/procstats/AssociationState.java
index 97f4b0f..a21a842 100644
--- a/core/java/com/android/internal/app/procstats/AssociationState.java
+++ b/core/java/com/android/internal/app/procstats/AssociationState.java
@@ -59,6 +59,7 @@
/**
* The state of the source process of an association.
*/
+ @SuppressWarnings("ParcelableCreator")
public static final class SourceState implements Parcelable {
private @NonNull final ProcessStats mProcessStats;
private @Nullable final AssociationState mAssociationState;
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 0a29fc52..eb62cb0 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -735,7 +735,7 @@
}
protected boolean shouldRecordDetailedData() {
- return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
+ return mRandom.nextInt(mPeriodicSamplingInterval) == 0;
}
/**
diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java
index e9d55db..1276fb9 100644
--- a/core/java/com/android/internal/os/BinderLatencyObserver.java
+++ b/core/java/com/android/internal/os/BinderLatencyObserver.java
@@ -236,7 +236,7 @@
}
protected boolean shouldKeepSample() {
- return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
+ return mRandom.nextInt(mPeriodicSamplingInterval) == 0;
}
/** Updates the sampling interval. */
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
index 2805dcc..0645eb7 100644
--- a/core/java/com/android/internal/os/LooperStats.java
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -290,7 +290,7 @@
}
protected boolean shouldCollectDetailedData() {
- return ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
+ return ThreadLocalRandom.current().nextInt(mSamplingInterval) == 0;
}
private static class DispatchSession {
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 8fcb6d5..4b7b91c 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -468,7 +468,7 @@
boolean shouldSample;
int traceThreshold;
synchronized (mLock) {
- shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
+ shouldSample = ThreadLocalRandom.current().nextInt(mSamplingInterval) == 0;
traceThreshold = mTraceThresholdPerAction[action];
}
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 32ce0fe..1ae1307 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -241,4 +241,4 @@
mSurfaceFrame.right = width;
mSurfaceFrame.bottom = height;
}
-};
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7ada548..196ea59 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6184,6 +6184,116 @@
android:label="@string/permlab_foregroundService"
android:protectionLevel="normal|instant" />
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "camera".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"
+ android:description="@string/permdesc_foregroundServiceCamera"
+ android:label="@string/permlab_foregroundServiceCamera"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "connectedDevice".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"
+ android:description="@string/permdesc_foregroundServiceConnectedDevice"
+ android:label="@string/permlab_foregroundServiceConnectedDevice"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "dataSync".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"
+ android:description="@string/permdesc_foregroundServiceDataSync"
+ android:label="@string/permlab_foregroundServiceDataSync"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "location".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"
+ android:description="@string/permdesc_foregroundServiceLocation"
+ android:label="@string/permlab_foregroundServiceLocation"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "mediaPlayback".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"
+ android:description="@string/permdesc_foregroundServiceMediaPlayback"
+ android:label="@string/permlab_foregroundServiceMediaPlayback"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "mediaProjection".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"
+ android:description="@string/permdesc_foregroundServiceMediaProjection"
+ android:label="@string/permlab_foregroundServiceMediaProjection"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "microphone".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"
+ android:description="@string/permdesc_foregroundServiceMicrophone"
+ android:label="@string/permlab_foregroundServiceMicrophone"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "phoneCall".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"
+ android:description="@string/permdesc_foregroundServicePhoneCall"
+ android:label="@string/permlab_foregroundServicePhoneCall"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "health".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH"
+ android:description="@string/permdesc_foregroundServiceHealth"
+ android:label="@string/permlab_foregroundServiceHealth"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "remoteMessaging".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING"
+ android:description="@string/permdesc_foregroundServiceRemoteMessaging"
+ android:label="@string/permlab_foregroundServiceRemoteMessaging"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "systemExempted".
+ Apps are allowed to use this type only in the use cases listed in
+ {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED}.
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"
+ android:description="@string/permdesc_foregroundServiceSystemExempted"
+ android:label="@string/permlab_foregroundServiceSystemExempted"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "specialUse".
+ <p>Protection level: signature|appop|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
+ android:description="@string/permdesc_foregroundServiceSpecialUse"
+ android:label="@string/permlab_foregroundServiceSpecialUse"
+ android:protectionLevel="signature|appop|instant" />
+
<!-- @SystemApi Allows to access all app shortcuts.
@hide -->
<permission android:name="android.permission.ACCESS_SHORTCUTS"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index eac2b94..607467a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1586,19 +1586,71 @@
together. -->
<attr name="foregroundServiceType">
<!-- Data (photo, file, account) upload/download, backup/restore, import/export, fetch,
- transfer over network between device and cloud. -->
+ transfer over network between device and cloud.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, this type should NOT
+ be used: calling
+ {@link android.app.Service#startForeground(int, android.app.Notification, int)} with
+ this type on devices running {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}
+ is still allowed, but calling it with this type on devices running future platform
+ releases may get a {@link android.app.ForegroundServiceTypeNotAllowedException}.
+ -->
<flag name="dataSync" value="0x01" />
- <!-- Music, video, news or other media play. -->
+ <!-- Music, video, news or other media play.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PLAYBACK}.
+ -->
<flag name="mediaPlayback" value="0x02" />
<!-- Ongoing operations related to phone calls, video conferencing,
- or similar interactive communication. -->
+ or similar interactive communication.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_PHONE_CALL} and
+ {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
+ -->
<flag name="phoneCall" value="0x04" />
- <!-- GPS, map, navigation location update. -->
+ <!-- GPS, map, navigation location update.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_LOCATION} and one of the
+ following permissions:
+ {@link android.Manifest.permission#ACCESS_COARSE_LOCATION},
+ {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ -->
<flag name="location" value="0x08" />
- <!-- Auto, bluetooth, TV or other devices connection, monitoring and interaction. -->
+ <!-- Auto, bluetooth, TV or other devices connection, monitoring and interaction.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_CONNECTED_DEVICE} and one of the
+ following permissions:
+ {@link android.Manifest.permission#BLUETOOTH_CONNECT},
+ {@link android.Manifest.permission#CHANGE_NETWORK_STATE},
+ {@link android.Manifest.permission#CHANGE_WIFI_STATE},
+ {@link android.Manifest.permission#CHANGE_WIFI_MULTICAST_STATE},
+ {@link android.Manifest.permission#NFC},
+ {@link android.Manifest.permission#TRANSMIT_IR},
+ or has been granted the access to one of the attached USB devices/accessories.
+ -->
<flag name="connectedDevice" value="0x10" />
<!-- Managing a media projection session, e.g, for screen recording or taking
- screenshots.-->
+ screenshots.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_MEDIA_PROJECTION}, and the user
+ must have allowed the screen capture request from this app.
+ -->
<flag name="mediaProjection" value="0x20" />
<!-- Use the camera device or record video.
@@ -1606,6 +1658,12 @@
and above, a foreground service will not be able to access the camera if this type is
not specified in the manifest and in
{@link android.app.Service#startForeground(int, android.app.Notification, int)}.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_CAMERA} and
+ {@link android.Manifest.permission#CAMERA}.
-->
<flag name="camera" value="0x40" />
<!--Use the microphone device or record audio.
@@ -1614,8 +1672,48 @@
and above, a foreground service will not be able to access the microphone if this type
is not specified in the manifest and in
{@link android.app.Service#startForeground(int, android.app.Notification, int)}.
+
+ <p>For apps with <code>targetSdkVersion</code>
+ {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, starting a foreground
+ service with this type will require permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_MICROPHONE} and one of the
+ following permissions:
+ {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT},
+ {@link android.Manifest.permission#RECORD_AUDIO}.
-->
<flag name="microphone" value="0x80" />
+ <!--Health, wellness and fitness.
+ <p>Requires the app to hold the permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_HEALTH} and one of the following
+ permissions
+ {@link android.Manifest.permission#ACTIVITY_RECOGNITION},
+ {@link android.Manifest.permission#BODY_SENSORS},
+ {@link android.Manifest.permission#HIGH_SAMPLING_RATE_SENSORS}.
+ -->
+ <flag name="health" value="0x100" />
+ <!-- Messaging use cases which host local server to relay messages across devices.
+ <p>Requires the app to hold the permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_REMOTE_MESSAGING} in order to use
+ this type.
+ -->
+ <flag name="remoteMessaging" value="0x200" />
+ <!-- The system exmpted foreground service use cases.
+ <p>Requires the app to hold the permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_SYSTEM_EXEMPTED} in order to use
+ this type. Apps are allowed to use this type only in the use cases listed in
+ {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED}.
+ -->
+ <flag name="systemExempted" value="0x400" />
+ <!-- Use cases that can't be categorized into any other foreground service types, but also
+ can't use @link android.app.job.JobInfo.Builder} APIs.
+ See {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE} for the
+ best practice of the use of this type.
+
+ <p>Requires the app to hold the permission
+ {@link android.Manifest.permission#FOREGROUND_SERVICE_SPECIAL_USE} in order to use
+ this type.
+ -->
+ <flag name="specialUse" value="0x40000000" />
</attr>
<!-- Enable sampled memory bug detection in this process.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ac383e6..932b24e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2434,7 +2434,7 @@
<!-- The duration in milliseconds of the dream opening animation. -->
<integer name="config_dreamOpenAnimationDuration">250</integer>
<!-- The duration in milliseconds of the dream closing animation. -->
- <integer name="config_dreamCloseAnimationDuration">100</integer>
+ <integer name="config_dreamCloseAnimationDuration">300</integer>
<!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 216975d..7714082 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1143,6 +1143,66 @@
<string name="permdesc_foregroundService">Allows the app to make use of foreground services.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceCamera">run foreground service with the type \"camera\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceCamera">Allows the app to make use of foreground services with the type \"camera\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceConnectedDevice">run foreground service with the type \"connectedDevice\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceConnectedDevice">Allows the app to make use of foreground services with the type \"connectedDevice\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceDataSync">run foreground service with the type \"dataSync\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceDataSync">Allows the app to make use of foreground services with the type \"dataSync\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceLocation">run foreground service with the type \"location\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceLocation">Allows the app to make use of foreground services with the type \"location\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceMediaPlayback">run foreground service with the type \"mediaPlayback\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceMediaPlayback">Allows the app to make use of foreground services with the type \"mediaPlayback\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceMediaProjection">run foreground service with the type \"mediaProjection\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceMediaProjection">Allows the app to make use of foreground services with the type \"mediaProjection\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceMicrophone">run foreground service with the type \"microphone\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceMicrophone">Allows the app to make use of foreground services with the type \"microphone\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServicePhoneCall">run foreground service with the type \"phoneCall\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServicePhoneCall">Allows the app to make use of foreground services with the type \"phoneCall\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceHealth">run foreground service with the type \"health\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceHealth">Allows the app to make use of foreground services with the type \"health\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceRemoteMessaging">run foreground service with the type \"remoteMessaging\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceRemoteMessaging">Allows the app to make use of foreground services with the type \"remoteMessaging\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceSystemExempted">run foreground service with the type \"systemExempted\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceSystemExempted">Allows the app to make use of foreground services with the type \"systemExempted\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_foregroundServiceSpecialUse">run foreground service with the type \"specialUse\"</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_foregroundServiceSpecialUse">Allows the app to make use of foreground services with the type \"specialUse\"</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_getPackageSize">measure app storage space</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_getPackageSize">Allows the app to retrieve its code, data, and cache sizes</string>
diff --git a/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
index 1cf4302..372bca4 100644
--- a/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
+++ b/core/tests/benchmarks/src/android/os/ParcelableBenchmark.java
@@ -88,6 +88,7 @@
}
}
+ @SuppressWarnings("ParcelableCreator")
@SuppressLint("ParcelCreator")
private static class PointArray implements Parcelable {
Rect mBounds = new Rect();
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java
index d505492..86e95832 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerPropertyTests.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import android.content.pm.PackageManager.Property;
@@ -162,40 +163,30 @@
@Test
public void testProperty_invalidName() throws Exception {
- try {
+ assertThrows(NullPointerException.class, () -> {
final Property p = new Property(null, 1, "android", null);
- fail("expected assertion error");
- } catch (AssertionError expected) {
- }
+ });
}
@Test
public void testProperty_invalidType() throws Exception {
- try {
+ assertThrows(IllegalArgumentException.class, () -> {
final Property p = new Property("invalidTypeProperty", 0, "android", null);
- fail("expected assertion error");
- } catch (AssertionError expected) {
- }
+ });
- try {
+ assertThrows(IllegalArgumentException.class, () -> {
final Property p = new Property("invalidTypeProperty", 6, "android", null);
- fail("expected assertion error");
- } catch (AssertionError expected) {
- }
+ });
- try {
+ assertThrows(IllegalArgumentException.class, () -> {
final Property p = new Property("invalidTypeProperty", -1, "android", null);
- fail("expected assertion error");
- } catch (AssertionError expected) {
- }
+ });
}
@Test
public void testProperty_noPackageName() throws Exception {
- try {
+ assertThrows(NullPointerException.class, () -> {
final Property p = new Property(null, 1, null, null);
- fail("expected assertion error");
- } catch (AssertionError expected) {
- }
+ });
}
}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 00b3693..bbf9f3c 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -128,6 +128,7 @@
RemoteViews clone = child.clone();
}
+ @SuppressWarnings("ReturnValueIgnored")
@Test
public void clone_repeatedly() {
RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test);
@@ -485,6 +486,7 @@
}
}
+ @SuppressWarnings("ReturnValueIgnored")
@Test
public void nestedAddViews() {
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
@@ -509,6 +511,7 @@
parcelAndRecreate(views);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Test
public void nestedLandscapeViews() {
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 82b2bf4..8207c9e 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -1054,10 +1054,23 @@
super(new Injector() {
public Random getRandomGenerator() {
return new Random() {
- int mCallCount = 0;
+ int mCallCount = -1;
public int nextInt() {
- return mCallCount++;
+ throw new IllegalStateException("Should not use nextInt()");
+ }
+
+ public int nextInt(int x) {
+ if (mCallCount == -1) {
+ // The tests are written such that they expect
+ // the first call to nextInt() to be on the first
+ // callEnded(). However, the BinderCallsStats
+ // constructor also calls nextInt(). Fake 0 being
+ // rolled twice.
+ mCallCount++;
+ return 0;
+ }
+ return (mCallCount++) % x;
}
};
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
index 5af7376..7bd53b9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderLatencyObserverTest.java
@@ -98,7 +98,7 @@
assertEquals(1, latencyHistograms.size());
LatencyDims dims = latencyHistograms.keySet().iterator().next();
assertEquals(binder.getClass(), dims.getBinderClass());
- assertEquals(1, dims.getTransactionCode());
+ assertEquals(2, dims.getTransactionCode()); // the first nextInt() is in the constructor
assertThat(latencyHistograms.get(dims)).asList().containsExactly(1, 0, 0, 0, 0).inOrder();
}
@@ -313,11 +313,11 @@
int mCallCount = 0;
public int nextInt() {
- return mCallCount++;
+ throw new IllegalStateException("Should not use nextInt()");
}
public int nextInt(int x) {
- return 1;
+ return (mCallCount++) % x;
}
};
}
diff --git a/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
index 6c50bce..8b30828 100644
--- a/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
@@ -16,6 +16,8 @@
package com.android.internal.util;
+import static org.junit.Assert.assertThrows;
+
import android.os.SystemClock;
import android.text.format.DateUtils;
@@ -170,10 +172,9 @@
}
void assertThrow(Fn fn) {
- try {
+ assertThrows(Throwable.class, () -> {
fn.call();
- fail("expected n exception to be thrown.");
- } catch (Throwable t) { }
+ });
}
interface Fn { void call(); }
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/Test.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/Test.java
index 41b8956f..a226325 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/Test.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/src/com/android/multidexlegacytestapp/Test.java
@@ -31,6 +31,7 @@
assertEquals(3366, getActivity().getValue());
}
+ @SuppressWarnings("ReturnValueIgnored")
public void testAnnotation() throws Exception {
assertEquals(ReferencedByAnnotation.B,
((AnnotationWithEnum) TestApplication.annotation).value());
diff --git a/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java b/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
index c53f4cc..1581abb 100644
--- a/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/CallbackRegistryTest.java
@@ -20,6 +20,7 @@
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -39,11 +40,11 @@
Integer argValue;
private void addNotifyCount(Integer callback) {
- if (callback == callback1) {
+ if (Objects.equals(callback, callback1)) {
notify1++;
- } else if (callback == callback2) {
+ } else if (Objects.equals(callback, callback2)) {
notify2++;
- } else if (callback == callback3) {
+ } else if (Objects.equals(callback, callback3)) {
notify3++;
}
deepNotifyCount[callback]++;
@@ -114,7 +115,7 @@
public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
int arg1, Integer arg) {
addNotifyCount(callback);
- if (callback == callback1) {
+ if (Objects.equals(callback, callback1)) {
registry.remove(callback1);
registry.remove(callback2);
}
@@ -166,9 +167,9 @@
public void onNotifyCallback(Integer callback, CallbackRegistryTest sender,
int arg1, Integer arg) {
addNotifyCount(callback);
- if (callback == callback1) {
+ if (Objects.equals(callback, callback1)) {
registry.remove(callback2);
- } else if (callback == callback3) {
+ } else if (Objects.equals(callback, callback3)) {
registry.add(callback2);
}
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index decfb9f..3e2b71f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -495,6 +495,10 @@
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
<!-- Permission required for CTS test - CtsTelephonyTestCases -->
<permission name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
+ <!-- Permission required for CTS test - CtsAppTestCases -->
+ <permission name="android.permission.CAPTURE_MEDIA_OUTPUT" />
+ <permission name="android.permission.CAPTURE_TUNER_AUDIO_INPUT" />
+ <permission name="android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
index 8706a68..42e3046 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientXmlChecker.java
@@ -168,6 +168,7 @@
*/
private static final Matcher<ExpressionTree> CONVERT_PRIMITIVE_TO_STRING =
new Matcher<ExpressionTree>() {
+ @SuppressWarnings("TreeToString") //TODO: Fix me
@Override
public boolean matches(ExpressionTree tree, VisitorState state) {
if (PRIMITIVE_TO_STRING.matches(tree, state)) {
@@ -205,6 +206,7 @@
*/
private static final Matcher<ExpressionTree> CONVERT_STRING_TO_PRIMITIVE =
new Matcher<ExpressionTree>() {
+ @SuppressWarnings("TreeToString") //TODO: Fix me
@Override
public boolean matches(ExpressionTree tree, VisitorState state) {
if (PRIMITIVE_PARSE.matches(tree, state)) {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 54c9f62..1a878df 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -766,7 +766,7 @@
if (mBackground != null) {
mBackground.onHotspotBoundsChanged();
}
- float newRadius = Math.round(getComputedRadius());
+ float newRadius = getComputedRadius();
for (int i = 0; i < mRunningAnimations.size(); i++) {
RippleAnimationSession s = mRunningAnimations.get(i);
s.setRadius(newRadius);
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 4065bd1..e25ee90 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -60,7 +60,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Map;
import java.util.Stack;
/**
@@ -1171,18 +1171,14 @@
private static final int NATIVE_ALLOCATION_SIZE = 100;
- private static final HashMap<String, Integer> sPropertyIndexMap =
- new HashMap<String, Integer>() {
- {
- put("translateX", TRANSLATE_X_INDEX);
- put("translateY", TRANSLATE_Y_INDEX);
- put("scaleX", SCALE_X_INDEX);
- put("scaleY", SCALE_Y_INDEX);
- put("pivotX", PIVOT_X_INDEX);
- put("pivotY", PIVOT_Y_INDEX);
- put("rotation", ROTATION_INDEX);
- }
- };
+ private static final Map<String, Integer> sPropertyIndexMap = Map.of(
+ "translateX", TRANSLATE_X_INDEX,
+ "translateY", TRANSLATE_Y_INDEX,
+ "scaleX", SCALE_X_INDEX,
+ "scaleY", SCALE_Y_INDEX,
+ "pivotX", PIVOT_X_INDEX,
+ "pivotY", PIVOT_Y_INDEX,
+ "rotation", ROTATION_INDEX);
static int getPropertyIndex(String propertyName) {
if (sPropertyIndexMap.containsKey(propertyName)) {
@@ -1285,18 +1281,15 @@
}
};
- private static final HashMap<String, Property> sPropertyMap =
- new HashMap<String, Property>() {
- {
- put("translateX", TRANSLATE_X);
- put("translateY", TRANSLATE_Y);
- put("scaleX", SCALE_X);
- put("scaleY", SCALE_Y);
- put("pivotX", PIVOT_X);
- put("pivotY", PIVOT_Y);
- put("rotation", ROTATION);
- }
- };
+ private static final Map<String, Property> sPropertyMap = Map.of(
+ "translateX", TRANSLATE_X,
+ "translateY", TRANSLATE_Y,
+ "scaleX", SCALE_X,
+ "scaleY", SCALE_Y,
+ "pivotX", PIVOT_X,
+ "pivotY", PIVOT_Y,
+ "rotation", ROTATION);
+
// Temp array to store transform values obtained from native.
private float[] mTransform;
/////////////////////////////////////////////////////
@@ -1762,19 +1755,15 @@
private static final int NATIVE_ALLOCATION_SIZE = 264;
// Property map for animatable attributes.
- private final static HashMap<String, Integer> sPropertyIndexMap
- = new HashMap<String, Integer> () {
- {
- put("strokeWidth", STROKE_WIDTH_INDEX);
- put("strokeColor", STROKE_COLOR_INDEX);
- put("strokeAlpha", STROKE_ALPHA_INDEX);
- put("fillColor", FILL_COLOR_INDEX);
- put("fillAlpha", FILL_ALPHA_INDEX);
- put("trimPathStart", TRIM_PATH_START_INDEX);
- put("trimPathEnd", TRIM_PATH_END_INDEX);
- put("trimPathOffset", TRIM_PATH_OFFSET_INDEX);
- }
- };
+ private static final Map<String, Integer> sPropertyIndexMap = Map.of(
+ "strokeWidth", STROKE_WIDTH_INDEX,
+ "strokeColor", STROKE_COLOR_INDEX,
+ "strokeAlpha", STROKE_ALPHA_INDEX,
+ "fillColor", FILL_COLOR_INDEX,
+ "fillAlpha", FILL_ALPHA_INDEX,
+ "trimPathStart", TRIM_PATH_START_INDEX,
+ "trimPathEnd", TRIM_PATH_END_INDEX,
+ "trimPathOffset", TRIM_PATH_OFFSET_INDEX);
// Below are the Properties that wrap the setters to avoid reflection overhead in animations
private static final Property<VFullPath, Float> STROKE_WIDTH =
@@ -1881,19 +1870,15 @@
}
};
- private final static HashMap<String, Property> sPropertyMap
- = new HashMap<String, Property> () {
- {
- put("strokeWidth", STROKE_WIDTH);
- put("strokeColor", STROKE_COLOR);
- put("strokeAlpha", STROKE_ALPHA);
- put("fillColor", FILL_COLOR);
- put("fillAlpha", FILL_ALPHA);
- put("trimPathStart", TRIM_PATH_START);
- put("trimPathEnd", TRIM_PATH_END);
- put("trimPathOffset", TRIM_PATH_OFFSET);
- }
- };
+ private static final Map<String, Property> sPropertyMap = Map.of(
+ "strokeWidth", STROKE_WIDTH,
+ "strokeColor", STROKE_COLOR,
+ "strokeAlpha", STROKE_ALPHA,
+ "fillColor", FILL_COLOR,
+ "fillAlpha", FILL_ALPHA,
+ "trimPathStart", TRIM_PATH_START,
+ "trimPathEnd", TRIM_PATH_END,
+ "trimPathOffset", TRIM_PATH_OFFSET);
// Temp array to store property data obtained from native getter.
private byte[] mPropertyData;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index a7fa2d9..16760e26 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -96,7 +96,7 @@
ActivityEmbeddingComponent {
static final String TAG = "SplitController";
static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
@VisibleForTesting
@GuardedBy("mLock")
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index d9eaeee..07cd7d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -611,8 +611,8 @@
mBackAnimationFinishedCallback = finishedCallback;
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()");
- runner.startAnimation(apps, wallpapers, nonApps,
- BackAnimationController.this::onBackAnimationFinished);
+ runner.startAnimation(apps, wallpapers, nonApps, () -> mShellExecutor.execute(
+ BackAnimationController.this::onBackAnimationFinished));
if (apps.length >= 1) {
dispatchOnBackStarted(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index c6f31c2..56d51bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -80,7 +80,7 @@
/** Set to {@code true} to enable shell transitions. */
public static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
&& SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index ca15f00..ebe5c5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -124,7 +124,8 @@
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration,
mDragStartListener);
CaptionTouchEventListener touchEventListener =
- new CaptionTouchEventListener(taskInfo, taskPositioner);
+ new CaptionTouchEventListener(taskInfo, taskPositioner,
+ windowDecoration.getDragDetector());
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragResizeCallback(taskPositioner);
setupWindowDecorationForTransition(taskInfo, startT, finishT);
@@ -173,16 +174,18 @@
private final int mTaskId;
private final WindowContainerToken mTaskToken;
private final DragResizeCallback mDragResizeCallback;
+ private final DragDetector mDragDetector;
private int mDragPointerId = -1;
- private boolean mDragActive = false;
private CaptionTouchEventListener(
RunningTaskInfo taskInfo,
- DragResizeCallback dragResizeCallback) {
+ DragResizeCallback dragResizeCallback,
+ DragDetector dragDetector) {
mTaskId = taskInfo.taskId;
mTaskToken = taskInfo.token;
mDragResizeCallback = dragResizeCallback;
+ mDragDetector = dragDetector;
}
@Override
@@ -231,19 +234,21 @@
@Override
public boolean onTouch(View v, MotionEvent e) {
+ boolean isDrag = false;
int id = v.getId();
if (id != R.id.caption_handle && id != R.id.caption) {
return false;
}
- if (id == R.id.caption_handle || mDragActive) {
+ if (id == R.id.caption_handle) {
+ isDrag = mDragDetector.detectDragEvent(e);
handleEventForMove(e);
}
if (e.getAction() != MotionEvent.ACTION_DOWN) {
- return false;
+ return isDrag;
}
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
if (taskInfo.isFocused) {
- return false;
+ return isDrag;
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reorder(mTaskToken, true /* onTop */);
@@ -251,6 +256,10 @@
return true;
}
+ /**
+ * @param e {@link MotionEvent} to process
+ * @return {@code true} if a drag is happening; or {@code false} if it is not
+ */
private void handleEventForMove(MotionEvent e) {
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
int windowingMode = mDesktopModeController
@@ -259,12 +268,12 @@
return;
}
switch (e.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mDragActive = true;
- mDragPointerId = e.getPointerId(0);
+ case MotionEvent.ACTION_DOWN: {
+ mDragPointerId = e.getPointerId(0);
mDragResizeCallback.onDragResizeStart(
0 /* ctrlType */, e.getRawX(0), e.getRawY(0));
break;
+ }
case MotionEvent.ACTION_MOVE: {
int dragPointerIdx = e.findPointerIndex(mDragPointerId);
mDragResizeCallback.onDragResizeMove(
@@ -273,7 +282,6 @@
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
- mDragActive = false;
int dragPointerIdx = e.findPointerIndex(mDragPointerId);
int statusBarHeight = mDisplayController.getDisplayLayout(taskInfo.displayId)
.stableInsets().top;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 03cad04..affde30 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -62,6 +62,8 @@
private boolean mDesktopActive;
+ private DragDetector mDragDetector;
+
private AdditionalWindow mHandleMenu;
CaptionWindowDecoration(
@@ -79,6 +81,7 @@
mChoreographer = choreographer;
mSyncQueue = syncQueue;
mDesktopActive = DesktopModeStatus.isActive(mContext);
+ mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
}
void setCaptionListeners(
@@ -92,6 +95,10 @@
mDragResizeCallback = dragResizeCallback;
}
+ DragDetector getDragDetector() {
+ return mDragDetector;
+ }
+
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
@@ -182,6 +189,8 @@
}
int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop();
+ mDragDetector.setTouchSlop(touchSlop);
+
int resize_handle = mResult.mRootView.getResources()
.getDimensionPixelSize(R.dimen.freeform_resize_handle);
int resize_corner = mResult.mRootView.getResources()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
new file mode 100644
index 0000000..0abe8ab
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragDetector.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 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.wm.shell.windowdecor;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.graphics.PointF;
+import android.view.MotionEvent;
+
+/**
+ * A detector for touch inputs that differentiates between drag and click inputs.
+ * All touch events must be passed through this class to track a drag event.
+ */
+public class DragDetector {
+ private int mTouchSlop;
+ private PointF mInputDownPoint;
+ private boolean mIsDragEvent;
+ private int mDragPointerId;
+ public DragDetector(int touchSlop) {
+ mTouchSlop = touchSlop;
+ mInputDownPoint = new PointF();
+ mIsDragEvent = false;
+ mDragPointerId = -1;
+ }
+
+ /**
+ * Determine if {@link MotionEvent} is part of a drag event.
+ * @return {@code true} if this is a drag event, {@code false} if not
+ */
+ public boolean detectDragEvent(MotionEvent ev) {
+ switch (ev.getAction()) {
+ case ACTION_DOWN: {
+ mDragPointerId = ev.getPointerId(0);
+ float rawX = ev.getRawX(0);
+ float rawY = ev.getRawY(0);
+ mInputDownPoint.set(rawX, rawY);
+ return false;
+ }
+ case ACTION_MOVE: {
+ if (!mIsDragEvent) {
+ int dragPointerIndex = ev.findPointerIndex(mDragPointerId);
+ float dx = ev.getRawX(dragPointerIndex) - mInputDownPoint.x;
+ float dy = ev.getRawY(dragPointerIndex) - mInputDownPoint.y;
+ if (Math.hypot(dx, dy) > mTouchSlop) {
+ mIsDragEvent = true;
+ }
+ }
+ return mIsDragEvent;
+ }
+ case ACTION_UP: {
+ boolean result = mIsDragEvent;
+ mIsDragEvent = false;
+ mInputDownPoint.set(0, 0);
+ mDragPointerId = -1;
+ return result;
+ }
+ case ACTION_CANCEL: {
+ mIsDragEvent = false;
+ mInputDownPoint.set(0, 0);
+ mDragPointerId = -1;
+ return false;
+ }
+ }
+ return mIsDragEvent;
+ }
+
+ public void setTouchSlop(int touchSlop) {
+ mTouchSlop = touchSlop;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index b9f16b6..48c0cea1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -22,7 +22,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import android.content.Context;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.input.InputManager;
@@ -38,6 +37,7 @@
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.SurfaceControl;
+import android.view.ViewConfiguration;
import android.view.WindowManagerGlobal;
import com.android.internal.view.BaseIWindow;
@@ -76,7 +76,7 @@
private Rect mRightBottomCornerBounds;
private int mDragPointerId = -1;
- private int mTouchSlop;
+ private DragDetector mDragDetector;
DragResizeInputListener(
Context context,
@@ -115,6 +115,7 @@
mInputEventReceiver = new TaskResizeInputEventReceiver(
mInputChannel, mHandler, mChoreographer);
mCallback = callback;
+ mDragDetector = new DragDetector(ViewConfiguration.get(context).getScaledTouchSlop());
}
/**
@@ -146,7 +147,7 @@
mHeight = height;
mResizeHandleThickness = resizeHandleThickness;
mCornerSize = cornerSize;
- mTouchSlop = touchSlop;
+ mDragDetector.setTouchSlop(touchSlop);
Region touchRegion = new Region();
final Rect topInputBounds = new Rect(0, 0, mWidth, mResizeHandleThickness);
@@ -228,7 +229,6 @@
private boolean mConsumeBatchEventScheduled;
private boolean mShouldHandleEvents;
private boolean mDragging;
- private final PointF mActionDownPoint = new PointF();
private TaskResizeInputEventReceiver(
InputChannel inputChannel, Handler handler, Choreographer choreographer) {
@@ -276,7 +276,9 @@
// Check if this is a touch event vs mouse event.
// Touch events are tracked in four corners. Other events are tracked in resize edges.
boolean isTouch = (e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN;
-
+ if (isTouch) {
+ mDragging = mDragDetector.detectDragEvent(e);
+ }
switch (e.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
float x = e.getX(0);
@@ -290,7 +292,6 @@
mDragPointerId = e.getPointerId(0);
float rawX = e.getRawX(0);
float rawY = e.getRawY(0);
- mActionDownPoint.set(rawX, rawY);
int ctrlType = calculateCtrlType(isTouch, x, y);
mCallback.onDragResizeStart(ctrlType, rawX, rawY);
result = true;
@@ -304,14 +305,7 @@
int dragPointerIndex = e.findPointerIndex(mDragPointerId);
float rawX = e.getRawX(dragPointerIndex);
float rawY = e.getRawY(dragPointerIndex);
- if (isTouch) {
- // Check for touch slop for touch events
- float dx = rawX - mActionDownPoint.x;
- float dy = rawY - mActionDownPoint.y;
- if (!mDragging && Math.hypot(dx, dy) > mTouchSlop) {
- mDragging = true;
- }
- } else {
+ if (!isTouch) {
// For all other types allow immediate dragging.
mDragging = true;
}
@@ -330,7 +324,6 @@
}
mDragging = false;
mShouldHandleEvents = false;
- mActionDownPoint.set(0, 0);
mDragPointerId = -1;
result = true;
break;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 1a1bebd..5ee8bf3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -61,7 +61,7 @@
@RunWith(AndroidJUnit4.class)
public final class StageTaskListenerTests extends ShellTestCase {
private static final boolean ENABLE_SHELL_TRANSITIONS =
- SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+ SystemProperties.getBoolean("persist.wm.debug.shell_transit", false);
@Mock
private ShellTaskOrganizer mTaskOrganizer;
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index 4f45602..a6da0a3 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -25,6 +25,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -125,7 +126,7 @@
* @hide
*/
public static GnssCapabilities empty() {
- return new GnssCapabilities(0, 0, 0, new ArrayList<>());
+ return new GnssCapabilities(0, 0, 0, Collections.emptyList());
}
private final @TopHalCapabilityFlags int mTopFlags;
@@ -142,7 +143,7 @@
mTopFlags = topFlags;
mMeasurementCorrectionsFlags = measurementCorrectionsFlags;
mPowerFlags = powerFlags;
- mGnssSignalTypes = gnssSignalTypes;
+ mGnssSignalTypes = Collections.unmodifiableList(gnssSignalTypes);
}
/**
@@ -155,7 +156,7 @@
return this;
} else {
return new GnssCapabilities(flags, mMeasurementCorrectionsFlags, mPowerFlags,
- new ArrayList<>(mGnssSignalTypes));
+ mGnssSignalTypes);
}
}
@@ -171,7 +172,7 @@
return this;
} else {
return new GnssCapabilities(mTopFlags, flags, mPowerFlags,
- new ArrayList<>(mGnssSignalTypes));
+ mGnssSignalTypes);
}
}
@@ -186,7 +187,7 @@
return this;
} else {
return new GnssCapabilities(mTopFlags, mMeasurementCorrectionsFlags, flags,
- new ArrayList<>(mGnssSignalTypes));
+ mGnssSignalTypes);
}
}
@@ -606,7 +607,7 @@
mTopFlags = 0;
mMeasurementCorrectionsFlags = 0;
mPowerFlags = 0;
- mGnssSignalTypes = new ArrayList<>();
+ mGnssSignalTypes = Collections.emptyList();
}
public Builder(@NonNull GnssCapabilities capabilities) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d975e96..17d7045 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2328,10 +2328,9 @@
return AudioSystem.SUCCESS;
}
- private final Map<Integer, Object> mDevRoleForCapturePresetListeners = new HashMap<>(){{
- put(AudioSystem.DEVICE_ROLE_PREFERRED,
- new DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>());
- }};
+ private final Map<Integer, Object> mDevRoleForCapturePresetListeners = Map.of(
+ AudioSystem.DEVICE_ROLE_PREFERRED,
+ new DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>());
private class DevRoleListenerInfo<T> {
final @NonNull Executor mExecutor;
@@ -6515,15 +6514,17 @@
// AudioPort implementation
//
- static final int AUDIOPORT_GENERATION_INIT = 0;
- static Integer sAudioPortGeneration = new Integer(AUDIOPORT_GENERATION_INIT);
- static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>();
- static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>();
- static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>();
+ private static final int AUDIOPORT_GENERATION_INIT = 0;
+ private static Object sAudioPortGenerationLock = new Object();
+ @GuardedBy("sAudioPortGenerationLock")
+ private static int sAudioPortGeneration = AUDIOPORT_GENERATION_INIT;
+ private static ArrayList<AudioPort> sAudioPortsCached = new ArrayList<AudioPort>();
+ private static ArrayList<AudioPort> sPreviousAudioPortsCached = new ArrayList<AudioPort>();
+ private static ArrayList<AudioPatch> sAudioPatchesCached = new ArrayList<AudioPatch>();
static int resetAudioPortGeneration() {
int generation;
- synchronized (sAudioPortGeneration) {
+ synchronized (sAudioPortGenerationLock) {
generation = sAudioPortGeneration;
sAudioPortGeneration = AUDIOPORT_GENERATION_INIT;
}
@@ -6533,7 +6534,7 @@
static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches,
ArrayList<AudioPort> previousPorts) {
sAudioPortEventHandler.init();
- synchronized (sAudioPortGeneration) {
+ synchronized (sAudioPortGenerationLock) {
if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) {
int[] patchGeneration = new int[1];
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
index ca175b4..0f962f9 100644
--- a/media/java/android/media/AudioMetadata.java
+++ b/media/java/android/media/AudioMetadata.java
@@ -30,6 +30,7 @@
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -446,14 +447,13 @@
// BaseMap is corresponding to audio_utils::metadata::Data
private static final int AUDIO_METADATA_OBJ_TYPE_BASEMAP = 6;
- private static final HashMap<Class, Integer> AUDIO_METADATA_OBJ_TYPES = new HashMap<>() {{
- put(Integer.class, AUDIO_METADATA_OBJ_TYPE_INT);
- put(Long.class, AUDIO_METADATA_OBJ_TYPE_LONG);
- put(Float.class, AUDIO_METADATA_OBJ_TYPE_FLOAT);
- put(Double.class, AUDIO_METADATA_OBJ_TYPE_DOUBLE);
- put(String.class, AUDIO_METADATA_OBJ_TYPE_STRING);
- put(BaseMap.class, AUDIO_METADATA_OBJ_TYPE_BASEMAP);
- }};
+ private static final Map<Class, Integer> AUDIO_METADATA_OBJ_TYPES = Map.of(
+ Integer.class, AUDIO_METADATA_OBJ_TYPE_INT,
+ Long.class, AUDIO_METADATA_OBJ_TYPE_LONG,
+ Float.class, AUDIO_METADATA_OBJ_TYPE_FLOAT,
+ Double.class, AUDIO_METADATA_OBJ_TYPE_DOUBLE,
+ String.class, AUDIO_METADATA_OBJ_TYPE_STRING,
+ BaseMap.class, AUDIO_METADATA_OBJ_TYPE_BASEMAP);
private static final Charset AUDIO_METADATA_CHARSET = StandardCharsets.UTF_8;
@@ -634,8 +634,8 @@
* Datum corresponds to Object
****************************************************************************************/
- private static final HashMap<Integer, DataPackage<?>> DATA_PACKAGES = new HashMap<>() {{
- put(AUDIO_METADATA_OBJ_TYPE_INT, new DataPackage<Integer>() {
+ private static final Map<Integer, DataPackage<?>> DATA_PACKAGES = Map.of(
+ AUDIO_METADATA_OBJ_TYPE_INT, new DataPackage<Integer>() {
@Override
@Nullable
public Integer unpack(ByteBuffer buffer) {
@@ -647,8 +647,8 @@
output.putInt(obj);
return true;
}
- });
- put(AUDIO_METADATA_OBJ_TYPE_LONG, new DataPackage<Long>() {
+ },
+ AUDIO_METADATA_OBJ_TYPE_LONG, new DataPackage<Long>() {
@Override
@Nullable
public Long unpack(ByteBuffer buffer) {
@@ -660,8 +660,8 @@
output.putLong(obj);
return true;
}
- });
- put(AUDIO_METADATA_OBJ_TYPE_FLOAT, new DataPackage<Float>() {
+ },
+ AUDIO_METADATA_OBJ_TYPE_FLOAT, new DataPackage<Float>() {
@Override
@Nullable
public Float unpack(ByteBuffer buffer) {
@@ -673,8 +673,8 @@
output.putFloat(obj);
return true;
}
- });
- put(AUDIO_METADATA_OBJ_TYPE_DOUBLE, new DataPackage<Double>() {
+ },
+ AUDIO_METADATA_OBJ_TYPE_DOUBLE, new DataPackage<Double>() {
@Override
@Nullable
public Double unpack(ByteBuffer buffer) {
@@ -686,8 +686,8 @@
output.putDouble(obj);
return true;
}
- });
- put(AUDIO_METADATA_OBJ_TYPE_STRING, new DataPackage<String>() {
+ },
+ AUDIO_METADATA_OBJ_TYPE_STRING, new DataPackage<String>() {
@Override
@Nullable
public String unpack(ByteBuffer buffer) {
@@ -713,9 +713,9 @@
output.put(valueArr);
return true;
}
- });
- put(AUDIO_METADATA_OBJ_TYPE_BASEMAP, new BaseMapPackage());
- }};
+ },
+ AUDIO_METADATA_OBJ_TYPE_BASEMAP, new BaseMapPackage());
+
// ObjectPackage is a special case that it is expected to unpack audio_utils::metadata::Datum,
// which contains data type and data size besides the payload for the data.
private static final ObjectPackage OBJECT_PACKAGE = new ObjectPackage();
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 85cd342..d51f1e1 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -48,8 +48,8 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.NioUtils;
-import java.util.HashMap;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -1867,26 +1867,24 @@
}
// General pair map
- private static final HashMap<String, Integer> CHANNEL_PAIR_MAP = new HashMap<>() {{
- put("front", AudioFormat.CHANNEL_OUT_FRONT_LEFT
- | AudioFormat.CHANNEL_OUT_FRONT_RIGHT);
- put("back", AudioFormat.CHANNEL_OUT_BACK_LEFT
- | AudioFormat.CHANNEL_OUT_BACK_RIGHT);
- put("front of center", AudioFormat.CHANNEL_OUT_FRONT_LEFT_OF_CENTER
- | AudioFormat.CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
- put("side", AudioFormat.CHANNEL_OUT_SIDE_LEFT
- | AudioFormat.CHANNEL_OUT_SIDE_RIGHT);
- put("top front", AudioFormat.CHANNEL_OUT_TOP_FRONT_LEFT
- | AudioFormat.CHANNEL_OUT_TOP_FRONT_RIGHT);
- put("top back", AudioFormat.CHANNEL_OUT_TOP_BACK_LEFT
- | AudioFormat.CHANNEL_OUT_TOP_BACK_RIGHT);
- put("top side", AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
- | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT);
- put("bottom front", AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_LEFT
- | AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_RIGHT);
- put("front wide", AudioFormat.CHANNEL_OUT_FRONT_WIDE_LEFT
- | AudioFormat.CHANNEL_OUT_FRONT_WIDE_RIGHT);
- }};
+ private static final Map<String, Integer> CHANNEL_PAIR_MAP = Map.of(
+ "front", AudioFormat.CHANNEL_OUT_FRONT_LEFT
+ | AudioFormat.CHANNEL_OUT_FRONT_RIGHT,
+ "back", AudioFormat.CHANNEL_OUT_BACK_LEFT
+ | AudioFormat.CHANNEL_OUT_BACK_RIGHT,
+ "front of center", AudioFormat.CHANNEL_OUT_FRONT_LEFT_OF_CENTER
+ | AudioFormat.CHANNEL_OUT_FRONT_RIGHT_OF_CENTER,
+ "side", AudioFormat.CHANNEL_OUT_SIDE_LEFT | AudioFormat.CHANNEL_OUT_SIDE_RIGHT,
+ "top front", AudioFormat.CHANNEL_OUT_TOP_FRONT_LEFT
+ | AudioFormat.CHANNEL_OUT_TOP_FRONT_RIGHT,
+ "top back", AudioFormat.CHANNEL_OUT_TOP_BACK_LEFT
+ | AudioFormat.CHANNEL_OUT_TOP_BACK_RIGHT,
+ "top side", AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
+ | AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT,
+ "bottom front", AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_LEFT
+ | AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_RIGHT,
+ "front wide", AudioFormat.CHANNEL_OUT_FRONT_WIDE_LEFT
+ | AudioFormat.CHANNEL_OUT_FRONT_WIDE_RIGHT);
/**
* Convenience method to check that the channel configuration (a.k.a channel mask) is supported
@@ -1924,7 +1922,7 @@
return false;
}
// Check all pairs to see that they are matched (front duplicated here).
- for (HashMap.Entry<String, Integer> e : CHANNEL_PAIR_MAP.entrySet()) {
+ for (Map.Entry<String, Integer> e : CHANNEL_PAIR_MAP.entrySet()) {
final int positionPair = e.getValue();
if ((channelConfig & positionPair) != 0
&& (channelConfig & positionPair) != positionPair) {
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 0c8cacd..524bde4 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -70,6 +70,7 @@
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
@@ -4836,12 +4837,13 @@
for (int i = 1; i < entryValues.length; ++i) {
final Pair<Integer, Integer> guessDataFormat = guessDataFormat(entryValues[i]);
int first = -1, second = -1;
- if (guessDataFormat.first == dataFormat.first
- || guessDataFormat.second == dataFormat.first) {
+ if (Objects.equals(guessDataFormat.first, dataFormat.first)
+ || Objects.equals(guessDataFormat.second, dataFormat.first)) {
first = dataFormat.first;
}
- if (dataFormat.second != -1 && (guessDataFormat.first == dataFormat.second
- || guessDataFormat.second == dataFormat.second)) {
+ if (dataFormat.second != -1
+ && (Objects.equals(guessDataFormat.first, dataFormat.second)
+ || Objects.equals(guessDataFormat.second, dataFormat.second))) {
second = dataFormat.second;
}
if (first == -1 && second == -1) {
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 3008067..2342a42 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -21,6 +21,8 @@
import android.os.IBinder;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookieStore;
@@ -31,7 +33,9 @@
public class MediaHTTPService extends IMediaHTTPService.Stub {
private static final String TAG = "MediaHTTPService";
@Nullable private List<HttpCookie> mCookies;
- private Boolean mCookieStoreInitialized = new Boolean(false);
+ private final Object mCookieStoreInitializedLock = new Object();
+ @GuardedBy("mCookieStoreInitializedLock")
+ private boolean mCookieStoreInitialized = false;
public MediaHTTPService(@Nullable List<HttpCookie> cookies) {
mCookies = cookies;
@@ -40,7 +44,7 @@
public IMediaHTTPConnection makeHTTPConnection() {
- synchronized (mCookieStoreInitialized) {
+ synchronized (mCookieStoreInitializedLock) {
// Only need to do it once for all connections
if ( !mCookieStoreInitialized ) {
CookieHandler cookieHandler = CookieHandler.getDefault();
@@ -78,8 +82,8 @@
Log.v(TAG, "makeHTTPConnection(" + this + "): cookieHandler: " + cookieHandler +
" Cookies: " + mCookies);
- } // mCookieStoreInitialized
- } // synchronized
+ }
+ }
return new MediaHTTPConnection();
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 77b5746..79a5902 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2507,6 +2507,8 @@
*
* @see android.media.MediaPlayer#getTrackInfo
*/
+ // The creator needs to be pulic, which requires removing the @UnsupportedAppUsage
+ @SuppressWarnings("ParcelableCreator")
static public class TrackInfo implements Parcelable {
/**
* Gets the track type.
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
index 84b9c9e..38fc717 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl
@@ -64,6 +64,7 @@
void notifyContentBlocked(in IBinder sessionToken, in String rating, int userId);
void notifySignalStrength(in IBinder sessionToken, int stength, int userId);
void notifyRecordingStarted(in IBinder sessionToken, in String recordingId, int userId);
+ void notifyRecordingStopped(in IBinder sessionToken, in String recordingId, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height,
int userId);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
index 95b4ffa..9e33536 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl
@@ -54,6 +54,7 @@
void notifyContentBlocked(in String rating);
void notifySignalStrength(int strength);
void notifyRecordingStarted(in String recordingId);
+ void notifyRecordingStopped(in String recordingId);
void setSurface(in Surface surface);
void dispatchSurfaceChanged(int format, int width, int height);
void notifyBroadcastInfoResponse(in BroadcastInfoResponse response);
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
index 042cb15..a2fdfe0 100644
--- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -82,6 +82,7 @@
private static final int DO_RELAYOUT_MEDIA_VIEW = 28;
private static final int DO_REMOVE_MEDIA_VIEW = 29;
private static final int DO_NOTIFY_RECORDING_STARTED = 30;
+ private static final int DO_NOTIFY_RECORDING_STOPPED = 31;
private final HandlerCaller mCaller;
private Session mSessionImpl;
@@ -169,6 +170,10 @@
mSessionImpl.notifyRecordingStarted((String) msg.obj);
break;
}
+ case DO_NOTIFY_RECORDING_STOPPED: {
+ mSessionImpl.notifyRecordingStopped((String) msg.obj);
+ break;
+ }
case DO_SEND_SIGNING_RESULT: {
SomeArgs args = (SomeArgs) msg.obj;
mSessionImpl.sendSigningResult((String) args.arg1, (byte[]) args.arg2);
@@ -392,6 +397,12 @@
}
@Override
+ public void notifyRecordingStopped(String recordingId) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(
+ DO_NOTIFY_RECORDING_STOPPED, recordingId));
+ }
+
+ @Override
public void setSurface(Surface surface) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface));
}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index 0f11407..287df40 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -1071,6 +1071,18 @@
}
}
+ void notifyRecordingStopped(String recordingId) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyRecordingStopped(mToken, recordingId, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
if (mToken == null) {
Log.w(TAG, "The session has been already released");
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 9ef6503..90eed9e 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -463,6 +463,16 @@
}
/**
+ * Receives stopped recording's ID.
+ *
+ * @param recordingId The ID of the recording stopped
+ * @hide
+ */
+ public void onRecordingStopped(@NonNull String recordingId) {
+ }
+
+
+ /**
* Receives signing result.
* @param signingId the ID to identify the request. It's the same as the corresponding ID in
* {@link Session#requestSigning(String, String, String, byte[])}
@@ -1178,11 +1188,21 @@
onAdResponse(response);
}
+ /**
+ * Calls {@link #onRecordingStarted(String)}.
+ */
void notifyRecordingStarted(String recordingId) {
onRecordingStarted(recordingId);
}
/**
+ * Calls {@link #onRecordingStopped(String)}.
+ */
+ void notifyRecordingStopped(String recordingId) {
+ onRecordingStopped(recordingId);
+ }
+
+ /**
* Notifies when the session state is changed.
*
* @param state the current session state.
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index c21b288..fcd781b 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -581,9 +581,10 @@
}
/**
- * Alerts the TV interactive app that a recording has been started with recordingId
+ * Alerts the TV interactive app that a recording has been started.
*
- * @param recordingId The ID of the recording started
+ * @param recordingId The ID of the recording started. This ID is created and maintained by the
+ * TV app and is used to identify the recording in the future.
*/
public void notifyRecordingStarted(@NonNull String recordingId) {
if (DEBUG) {
@@ -595,6 +596,23 @@
}
/**
+ * Alerts the TV interactive app that a recording has been stopped.
+ *
+ * @param recordingId The ID of the recording stopped. This ID is created and maintained
+ * by the TV app when a recording is started.
+ * @see TvInteractiveAppView#notifyRecordingStarted(String)
+ * @hide
+ */
+ public void notifyRecordingStopped(@NonNull String recordingId) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyRecordingStopped");
+ }
+ if (mSession != null) {
+ mSession.notifyRecordingStopped(recordingId);
+ }
+ }
+
+ /**
* Sends signing result to related TV interactive app.
*
* <p>This is used when the corresponding server of the broadcast-independent interactive
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 51b976b..fab63aa 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -2376,19 +2376,20 @@
}
/**
- * Request a frontend by frontend id.
+ * Request a frontend by frontend info.
*
* <p> This API is used if the applications want to select a desired frontend before
* {@link tune} to use a specific satellite or sending SatCR DiSEqC command for {@link tune}.
*
- * @param desiredId the desired fronted Id. It can be retrieved by
+ * @param desiredFrontendInfo the FrontendInfo of the desired fronted. It can be retrieved by
* {@link getAvailableFrontendInfos}
*
* @return result status of open operation.
* @throws SecurityException if the caller does not have appropriate permissions.
*/
@Result
- public int requestFrontendById(int desiredId) {
+ public int applyFrontend(@NonNull FrontendInfo desiredFrontendInfo) {
+ Objects.requireNonNull(desiredFrontendInfo, "desiredFrontendInfo must not be null");
mFrontendLock.lock();
try {
if (mFeOwnerTuner != null) {
@@ -2399,17 +2400,12 @@
Log.e(TAG, "A frontend has been opened before");
return RESULT_INVALID_STATE;
}
- FrontendInfo frontendInfo = getFrontendInfoById(desiredId);
- if (frontendInfo == null) {
- Log.e(TAG, "Failed to get a FrontendInfo by frontend id: " + desiredId);
- return RESULT_UNAVAILABLE;
- }
- int frontendType = frontendInfo.getType();
+ mFrontendType = desiredFrontendInfo.getType();
+ mDesiredFrontendId = desiredFrontendInfo.getId();
if (DEBUG) {
- Log.d(TAG, "Opening frontend with type " + frontendType + ", id " + desiredId);
+ Log.d(TAG, "Applying frontend with type " + mFrontendType + ", id "
+ + mDesiredFrontendId);
}
- mFrontendType = frontendType;
- mDesiredFrontendId = desiredId;
if (!checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, mFrontendLock)) {
return RESULT_UNAVAILABLE;
}
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index 1a65832..4bcc3c6 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -28,6 +28,7 @@
import android.os.Process;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FrameworkStatsLog;
import java.util.concurrent.Executor;
@@ -48,7 +49,9 @@
private static int sInstantId = 0;
private int mSegmentId = 0;
private int mOverflow;
- private Boolean mIsStopped = true;
+ private final Object mIsStoppedLock = new Object();
+ @GuardedBy("mIsStoppedLock")
+ private boolean mIsStopped = true;
private final Object mListenerLock = new Object();
private native int nativeAttachFilter(Filter filter);
@@ -178,7 +181,7 @@
.write(FrameworkStatsLog.TV_TUNER_DVR_STATUS, mUserId,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__TYPE__RECORD,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__STATE__STARTED, mSegmentId, 0);
- synchronized (mIsStopped) {
+ synchronized (mIsStoppedLock) {
int result = nativeStartDvr();
if (result == Tuner.RESULT_SUCCESS) {
mIsStopped = false;
@@ -201,7 +204,7 @@
.write(FrameworkStatsLog.TV_TUNER_DVR_STATUS, mUserId,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__TYPE__RECORD,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__STATE__STOPPED, mSegmentId, mOverflow);
- synchronized (mIsStopped) {
+ synchronized (mIsStoppedLock) {
int result = nativeStopDvr();
if (result == Tuner.RESULT_SUCCESS) {
mIsStopped = true;
@@ -219,7 +222,7 @@
*/
@Result
public int flush() {
- synchronized (mIsStopped) {
+ synchronized (mIsStoppedLock) {
if (mIsStopped) {
return nativeFlushDvr();
}
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index aff2e1b4..89e5e0d 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -230,7 +230,7 @@
case MtpConstants.PROPERTY_PERSISTENT_UID:
// The persistent uid must be unique and never reused among all objects,
// and remain the same between sessions.
- long puid = (object.getPath().toString().hashCode() << 32)
+ long puid = (((long) object.getPath().toString().hashCode()) << 32)
+ object.getModifiedTime();
list.append(id, property.code, property.type, puid);
break;
diff --git a/media/mca/effect/java/android/media/effect/EffectFactory.java b/media/mca/effect/java/android/media/effect/EffectFactory.java
index f6fcba7..cbb2736 100644
--- a/media/mca/effect/java/android/media/effect/EffectFactory.java
+++ b/media/mca/effect/java/android/media/effect/EffectFactory.java
@@ -486,11 +486,9 @@
private Effect instantiateEffect(Class effectClass, String name) {
// Make sure this is an Effect subclass
- try {
- effectClass.asSubclass(Effect.class);
- } catch (ClassCastException e) {
+ if (!Effect.class.isAssignableFrom(effectClass)) {
throw new IllegalArgumentException("Attempting to allocate effect '" + effectClass
- + "' which is not a subclass of Effect!", e);
+ + "' which is not a subclass of Effect!");
}
// Look for the correct constructor
diff --git a/media/mca/filterfw/java/android/filterfw/core/Filter.java b/media/mca/filterfw/java/android/filterfw/core/Filter.java
index a608ef5..e82c046 100644
--- a/media/mca/filterfw/java/android/filterfw/core/Filter.java
+++ b/media/mca/filterfw/java/android/filterfw/core/Filter.java
@@ -90,9 +90,7 @@
return false;
}
// Then make sure it's a subclass of Filter.
- try {
- filterClass.asSubclass(Filter.class);
- } catch (ClassCastException e) {
+ if (!Filter.class.isAssignableFrom(filterClass)) {
return false;
}
return true;
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java b/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java
index 779df99..736e511 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterFactory.java
@@ -112,9 +112,7 @@
public Filter createFilterByClass(Class filterClass, String filterName) {
// Make sure this is a Filter subclass
- try {
- filterClass.asSubclass(Filter.class);
- } catch (ClassCastException e) {
+ if (!Filter.class.isAssignableFrom(filterClass)) {
throw new IllegalArgumentException("Attempting to allocate class '" + filterClass
+ "' which is not a subclass of Filter!");
}
diff --git a/media/mca/filterfw/java/android/filterfw/core/KeyValueMap.java b/media/mca/filterfw/java/android/filterfw/core/KeyValueMap.java
index 8cf9a13..6ff1885 100644
--- a/media/mca/filterfw/java/android/filterfw/core/KeyValueMap.java
+++ b/media/mca/filterfw/java/android/filterfw/core/KeyValueMap.java
@@ -55,12 +55,12 @@
public int getInt(String key) {
Object result = get(key);
- return result != null ? (Integer)result : null;
+ return result != null ? (Integer) result : 0;
}
public float getFloat(String key) {
Object result = get(key);
- return result != null ? (Float)result : null;
+ return result != null ? (Float) result : 0;
}
@Override
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index c5281657..8c05725 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -296,7 +296,7 @@
mMemWriter.write("End Memory :" + mEndMemory + "\n");
}
} catch (Exception e) {
- e.toString();
+ // TODO
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index 39add7e..c814eba 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -264,8 +264,14 @@
builder.append("**");
}
- if (elem instanceof Number) {
- builder.append(String.format("%x", elem));
+ if (elem instanceof Byte) {
+ builder.append(String.format("%x", (Byte) elem));
+ } else if (elem instanceof Short) {
+ builder.append(String.format("%x", (Short) elem));
+ } else if (elem instanceof Integer) {
+ builder.append(String.format("%x", (Integer) elem));
+ } else if (elem instanceof Long) {
+ builder.append(String.format("%x", (Long) elem));
} else {
builder.append(elem);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java
index fd1c2d3..37dd4b5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerGetCurrentPositionStateUnitTest.java
@@ -18,7 +18,7 @@
import android.media.MediaPlayer;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;;
+import android.test.suitebuilder.annotation.LargeTest;
/**
* Unit test class to test the set of valid and invalid states that
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 8a19709..3dcdf00 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -15,7 +15,7 @@
<string name="ssl_error_continue">Continue anyway via browser</string>
<!-- Telephony notification channel name for network boost notifications. -->
- <string name="network_boost_notification_channel">Network Boost</string>
+ <string name="network_boost_notification_channel">Network boost</string>
<!-- Notification title text for the network boost notification. -->
<string name="network_boost_notification_title">%s recommends a data boost</string>
<!-- Notification detail text for the network boost notification. -->
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
index dd7b218..b322b8b 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
@@ -240,11 +240,15 @@
return;
}
- context.getSystemService(NotificationManager.class).createNotificationChannel(
- new NotificationChannel(NETWORK_BOOST_NOTIFICATION_CHANNEL_ID,
- context.getResources().getString(
- R.string.network_boost_notification_channel),
- NotificationManager.IMPORTANCE_DEFAULT));
+ NotificationChannel channel = new NotificationChannel(
+ NETWORK_BOOST_NOTIFICATION_CHANNEL_ID,
+ context.getResources().getString(R.string.network_boost_notification_channel),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ // CarrierDefaultApp notifications are unblockable by default. Make this channel blockable
+ // to allow users to disable notifications posted to this channel without affecting other
+ // notifications in this application.
+ channel.setBlockable(true);
+ context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
Notification notification =
new Notification.Builder(context, NETWORK_BOOST_NOTIFICATION_CHANNEL_ID)
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index a7e1a59..ae40460 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -203,6 +203,7 @@
initUI();
}
+ @SuppressWarnings("MissingSuperCall") // TODO: Fix me
@Override
protected void onNewIntent(Intent intent) {
// Force cancels the CDM dialog if this activity receives another intent with
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
index 93e6271..3029d10 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
@@ -55,18 +55,15 @@
private static final String PRIVET_SERVICE = "_privet._tcp";
/** The required mDNS service types */
- private static final Set<String> PRINTER_SERVICE_TYPE = new HashSet<String>() {{
- // Not checking _printer_._sub
- add(PRIVET_SERVICE);
- }};
+ private static final Set<String> PRINTER_SERVICE_TYPE = Set.of(
+ PRIVET_SERVICE); // Not checking _printer_._sub
/** All possible connection states */
- private static final Set<String> POSSIBLE_CONNECTION_STATES = new HashSet<String>() {{
- add("online");
- add("offline");
- add("connecting");
- add("not-configured");
- }};
+ private static final Set<String> POSSIBLE_CONNECTION_STATES = Set.of(
+ "online",
+ "offline",
+ "connecting",
+ "not-configured");
private static final byte SUPPORTED_TXTVERS = '1';
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
index 34e7e3d..0c5de27 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
@@ -37,9 +37,7 @@
public class MDNSFilterPlugin implements PrintServicePlugin {
/** The mDNS service types supported */
- private static final Set<String> PRINTER_SERVICE_TYPES = new HashSet<String>() {{
- add("_ipp._tcp");
- }};
+ private static final Set<String> PRINTER_SERVICE_TYPES = Set.of("_ipp._tcp");
/**
* The printer filter for {@link MDNSFilteredDiscovery} passing only mDNS results
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
index d03bb1d..b9983c3 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterMopria.java
@@ -23,7 +23,6 @@
import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
import com.android.printservice.recommendation.util.MDNSUtils;
-import java.util.HashSet;
import java.util.Set;
/**
@@ -32,10 +31,7 @@
class PrinterFilterMopria implements MDNSFilteredDiscovery.PrinterFilter {
private static final String TAG = "PrinterFilterMopria";
- static final Set<String> MOPRIA_MDNS_SERVICES = new HashSet<String>() {{
- add("_ipp._tcp");
- add("_ipps._tcp");
- }};
+ static final Set<String> MOPRIA_MDNS_SERVICES = Set.of("_ipp._tcp", "_ipps._tcp");
private static final String PDL__PDF = "application/pdf";
private static final String PDL__PCLM = "application/PCLm";
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
index b9b9098..680dd84 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/PrinterFilterSamsung.java
@@ -25,7 +25,6 @@
import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
import com.android.printservice.recommendation.util.MDNSUtils;
-import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -36,9 +35,7 @@
class PrinterFilterSamsung implements MDNSFilteredDiscovery.PrinterFilter {
private static final String TAG = "PrinterFilterSamsung";
- static final Set<String> SAMSUNG_MDNS_SERVICES = new HashSet<String>() {{
- add("_pdl-datastream._tcp");
- }};
+ static final Set<String> SAMSUNG_MDNS_SERVICES = Set.of("_pdl-datastream._tcp");
private static final String[] NOT_SUPPORTED_MODELS = new String[]{
"SCX-5x15",
@@ -57,9 +54,7 @@
private static final String ATTR_PRODUCT = "product";
private static final String ATTR_TY = "ty";
- private static Set<String> SAMUNG_VENDOR_SET = new HashSet<String>() {{
- add("samsung");
- }};
+ private static final Set<String> SAMUNG_VENDOR_SET = Set.of("samsung");
@Override
public boolean matchesCriteria(NsdServiceInfo nsdServiceInfo) {
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
index ae1bdce..cbd5833 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/samsung/SamsungRecommendationPlugin.java
@@ -29,10 +29,11 @@
import java.util.Set;
public class SamsungRecommendationPlugin implements PrintServicePlugin {
- private static final Set<String> ALL_MDNS_SERVICES = new HashSet<String>() {{
- addAll(PrinterFilterMopria.MOPRIA_MDNS_SERVICES);
- addAll(PrinterFilterSamsung.SAMSUNG_MDNS_SERVICES);
- }};
+ private static final Set<String> ALL_MDNS_SERVICES = new HashSet<String>();
+ static {
+ ALL_MDNS_SERVICES.addAll(PrinterFilterMopria.MOPRIA_MDNS_SERVICES);
+ ALL_MDNS_SERVICES.addAll(PrinterFilterSamsung.SAMSUNG_MDNS_SERVICES);
+ }
private final @NonNull Context mContext;
private final @NonNull MDNSFilteredDiscovery mMDNSFilteredDiscovery;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index 00b3736..b0aa8f1 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -402,7 +402,7 @@
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
- if ((isOptionsClosed() || isOptionsClosed()) && dy <= 0) {
+ if (isOptionsClosed() && dy <= 0) {
return;
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
index 373b57f..a7122d0 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
@@ -54,6 +54,14 @@
)
/**
+ * Gets the group title of this item.
+ *
+ * Note: Items should be sorted by group in [getComparator] first, this [getGroupTitle] will not
+ * change the list order.
+ */
+ fun getGroupTitle(option: Int, record: T): String? = null
+
+ /**
* Gets the summary for the given app record.
*
* @return null if no summary should be displayed.
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
index 7f5fe9f..681eb1c 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
@@ -34,9 +34,11 @@
import com.android.settingslib.spa.framework.compose.TimeMeasurer.Companion.rememberTimeMeasurer
import com.android.settingslib.spa.framework.compose.rememberLazyListStateAndHideKeyboardWhenStartScroll
import com.android.settingslib.spa.framework.compose.toState
+import com.android.settingslib.spa.widget.ui.CategoryTitle
import com.android.settingslib.spa.widget.ui.PlaceholderTitle
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser
+import com.android.settingslib.spaprivileged.model.app.AppEntry
import com.android.settingslib.spaprivileged.model.app.AppListConfig
import com.android.settingslib.spaprivileged.model.app.AppListData
import com.android.settingslib.spaprivileged.model.app.AppListModel
@@ -100,17 +102,28 @@
}
items(count = list.size, key = { option to list[it].record.app.packageName }) {
+ remember(list) { listModel.getGroupTitleIfFirst(option, list, it) }
+ ?.let { group -> CategoryTitle(title = group) }
+
val appEntry = list[it]
val summary = listModel.getSummary(option, appEntry.record) ?: "".toState()
- val itemModel = remember(appEntry) {
+ appItem(remember(appEntry) {
AppListItemModel(appEntry.record, appEntry.label, summary)
- }
- appItem(itemModel)
+ })
}
}
}
}
+/** Returns group title if this is the first item of the group. */
+private fun <T : AppRecord> AppListModel<T>.getGroupTitleIfFirst(
+ option: Int,
+ list: List<AppEntry<T>>,
+ index: Int,
+): String? = getGroupTitle(option, list[index].record)?.takeIf {
+ index == 0 || it != getGroupTitle(option, list[index - 1].record)
+}
+
@Composable
private fun <T : AppRecord> loadAppListData(
config: AppListConfig,
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt
index 80c4eac..9f20c78 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt
@@ -58,26 +58,43 @@
@Test
fun couldShowAppItem() {
- setContent(appEntries = listOf(APP_ENTRY))
+ setContent(appEntries = listOf(APP_ENTRY_A))
- composeTestRule.onNodeWithText(APP_ENTRY.label).assertIsDisplayed()
+ composeTestRule.onNodeWithText(APP_ENTRY_A.label).assertIsDisplayed()
}
@Test
fun couldShowHeader() {
- setContent(header = { Text(HEADER) }, appEntries = listOf(APP_ENTRY))
+ setContent(appEntries = listOf(APP_ENTRY_A), header = { Text(HEADER) })
composeTestRule.onNodeWithText(HEADER).assertIsDisplayed()
}
+ @Test
+ fun whenNotGrouped_groupTitleDoesNotExist() {
+ setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = false)
+
+ composeTestRule.onNodeWithText(GROUP_A).assertDoesNotExist()
+ composeTestRule.onNodeWithText(GROUP_B).assertDoesNotExist()
+ }
+
+ @Test
+ fun whenGrouped_groupTitleDisplayed() {
+ setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = true)
+
+ composeTestRule.onNodeWithText(GROUP_A).assertIsDisplayed()
+ composeTestRule.onNodeWithText(GROUP_B).assertIsDisplayed()
+ }
+
private fun setContent(
- header: @Composable () -> Unit = {},
appEntries: List<AppEntry<TestAppRecord>>,
+ header: @Composable () -> Unit = {},
+ enableGrouping: Boolean = false,
) {
composeTestRule.setContent {
AppList(
config = AppListConfig(userId = USER_ID, showInstantApps = false),
- listModel = TestAppListModel(),
+ listModel = TestAppListModel(enableGrouping),
state = AppListState(
showSystem = false.toState(),
option = 0.toState(),
@@ -96,17 +113,37 @@
private companion object {
const val USER_ID = 0
const val HEADER = "Header"
- val APP_ENTRY = AppEntry(
- record = TestAppRecord(ApplicationInfo()),
- label = "AAA",
+ const val GROUP_A = "Group A"
+ const val GROUP_B = "Group B"
+ val APP_ENTRY_A = AppEntry(
+ record = TestAppRecord(
+ app = ApplicationInfo().apply {
+ packageName = "package.name.a"
+ },
+ group = GROUP_A,
+ ),
+ label = "Label A",
+ labelCollationKey = CollationKey("", byteArrayOf()),
+ )
+ val APP_ENTRY_B = AppEntry(
+ record = TestAppRecord(
+ app = ApplicationInfo().apply {
+ packageName = "package.name.b"
+ },
+ group = GROUP_B,
+ ),
+ label = "Label B",
labelCollationKey = CollationKey("", byteArrayOf()),
)
}
}
-private data class TestAppRecord(override val app: ApplicationInfo) : AppRecord
+private data class TestAppRecord(
+ override val app: ApplicationInfo,
+ val group: String? = null,
+) : AppRecord
-private class TestAppListModel : AppListModel<TestAppRecord> {
+private class TestAppListModel(val enableGrouping: Boolean) : AppListModel<TestAppRecord> {
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
appListFlow.asyncMapItem { TestAppRecord(it) }
@@ -118,4 +155,7 @@
option: Int,
recordListFlow: Flow<List<TestAppRecord>>,
) = recordListFlow
+
+ override fun getGroupTitle(option: Int, record: TestAppRecord) =
+ if (enableGrouping) record.group else null
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
index 6ce72bb..3af64e2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -82,4 +82,4 @@
Log.e(TAG, "localBluetoothAdapter is NULL!!");
}
}
-};
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 90fab08..2e4a245 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -720,6 +720,57 @@
<!-- Permission required for CTS test - CtsDeviceLockTestCases -->
<uses-permission android:name="android.permission.MANAGE_DEVICE_LOCK_STATE" />
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
+
+ <!-- Permission required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
+
+ <!-- Permissions required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.CAPTURE_MEDIA_OUTPUT" />
+
+ <!-- Permissions required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.CAPTURE_TUNER_AUDIO_INPUT" />
+
+ <!-- Permissions required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT" />
+
+ <!-- Permissions required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
+
+ <!-- Permissions required for CTS test - CtsAppFgsTestCases -->
+ <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 55d6379..f4d802b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -743,12 +743,35 @@
<!-- How long in milliseconds before full burn-in protection is achieved. -->
<integer name="config_dreamOverlayMillisUntilFullJitter">240000</integer>
+ <!-- The duration in milliseconds of the y-translation animation when waking up from
+ the dream -->
+ <integer name="config_dreamOverlayOutTranslationYDurationMs">333</integer>
+ <!-- The delay in milliseconds of the y-translation animation when waking up from
+ the dream for the complications at the bottom of the screen -->
+ <integer name="config_dreamOverlayOutTranslationYDelayBottomMs">33</integer>
+ <!-- The delay in milliseconds of the y-translation animation when waking up from
+ the dream for the complications at the top of the screen -->
+ <integer name="config_dreamOverlayOutTranslationYDelayTopMs">117</integer>
+ <!-- The duration in milliseconds of the alpha animation when waking up from the dream -->
+ <integer name="config_dreamOverlayOutAlphaDurationMs">200</integer>
+ <!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
+ complications at the top of the screen -->
+ <integer name="config_dreamOverlayOutAlphaDelayTopMs">217</integer>
+ <!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
+ complications at the bottom of the screen -->
+ <integer name="config_dreamOverlayOutAlphaDelayBottomMs">133</integer>
+ <!-- The duration in milliseconds of the blur animation when waking up from
+ the dream -->
+ <integer name="config_dreamOverlayOutBlurDurationMs">250</integer>
+
<integer name="complicationFadeOutMs">500</integer>
<integer name="complicationFadeInMs">500</integer>
<integer name="complicationRestoreMs">1000</integer>
+ <integer name="complicationFadeOutDelayMs">200</integer>
+
<!-- Duration in milliseconds of the dream in un-blur animation. -->
<integer name="config_dreamOverlayInBlurDurationMs">249</integer>
<!-- Delay in milliseconds of the dream in un-blur animation. -->
@@ -780,27 +803,6 @@
<item>com.android.systemui</item>
</string-array>
- <!-- The thresholds which determine the color used by the AQI dream overlay.
- NOTE: This must always be kept sorted from low to high -->
- <integer-array name="config_dreamAqiThresholds">
- <item>-1</item>
- <item>50</item>
- <item>100</item>
- <item>150</item>
- <item>200</item>
- <item>300</item>
- </integer-array>
-
- <!-- The color values which correspond to the thresholds above -->
- <integer-array name="config_dreamAqiColorValues">
- <item>@color/dream_overlay_aqi_good</item>
- <item>@color/dream_overlay_aqi_moderate</item>
- <item>@color/dream_overlay_aqi_unhealthy_sensitive</item>
- <item>@color/dream_overlay_aqi_unhealthy</item>
- <item>@color/dream_overlay_aqi_very_unhealthy</item>
- <item>@color/dream_overlay_aqi_hazardous</item>
- </integer-array>
-
<!-- Whether the device should display hotspot UI. If true, UI will display only when tethering
is available. If false, UI will never show regardless of tethering availability" -->
<bool name="config_show_wifi_tethering">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6577b07..fbdccff 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1552,6 +1552,7 @@
<dimen name="dream_overlay_complication_margin">0dp</dimen>
<dimen name="dream_overlay_y_offset">80dp</dimen>
+ <dimen name="dream_overlay_exit_y_offset">40dp</dimen>
<dimen name="dream_aqi_badge_corner_radius">28dp</dimen>
<dimen name="dream_aqi_badge_padding_vertical">6dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 80dff856..eb291fd 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -405,8 +405,8 @@
<string name="keyguard_face_failed">Can\u2019t recognize face</string>
<!-- Message shown to suggest using fingerprint sensor to authenticate after another biometric failed. [CHAR LIMIT=25] -->
<string name="keyguard_suggest_fingerprint">Use fingerprint instead</string>
- <!-- Message shown to inform the user that face unlock is not available. [CHAR LIMIT=65] -->
- <string name="keyguard_face_unlock_unavailable">Face unlock unavailable.</string>
+ <!-- Message shown to inform the user that face unlock is not available. [CHAR LIMIT=59] -->
+ <string name="keyguard_face_unlock_unavailable">Face Unlock unavailable</string>
<!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 0a2dc5b..d60cc75 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -291,8 +291,11 @@
mA11yManager.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK);
mA11yManager.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME);
mA11yManager.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS);
- mA11yManager.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
- mA11yManager.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+ if (mCentralSurfacesOptionalLazy.get().isPresent()) {
+ // These two actions require the CentralSurfaces instance.
+ mA11yManager.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
+ mA11yManager.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+ }
mA11yManager.registerSystemAction(actionPowerDialog, SYSTEM_ACTION_ID_POWER_DIALOG);
mA11yManager.registerSystemAction(actionLockScreen, SYSTEM_ACTION_ID_LOCK_SCREEN);
mA11yManager.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index d8dd6a2..0087c84 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -17,17 +17,19 @@
package com.android.systemui.dreams
import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.view.View
+import android.view.animation.Interpolator
+import androidx.annotation.FloatRange
import androidx.core.animation.doOnEnd
import com.android.systemui.animation.Interpolators
import com.android.systemui.dreams.complication.ComplicationHostViewController
import com.android.systemui.dreams.complication.ComplicationLayoutParams
+import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position
import com.android.systemui.dreams.dagger.DreamOverlayModule
import com.android.systemui.statusbar.BlurUtils
-import java.util.function.Consumer
+import com.android.systemui.statusbar.CrossFadeHelper
import javax.inject.Inject
import javax.inject.Named
@@ -40,108 +42,239 @@
private val mStatusBarViewController: DreamOverlayStatusBarViewController,
private val mOverlayStateController: DreamOverlayStateController,
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
- private val mDreamInBlurAnimDuration: Int,
- @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY) private val mDreamInBlurAnimDelay: Int,
+ private val mDreamInBlurAnimDurationMs: Long,
+ @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY)
+ private val mDreamInBlurAnimDelayMs: Long,
@Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
- private val mDreamInComplicationsAnimDuration: Int,
+ private val mDreamInComplicationsAnimDurationMs: Long,
@Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
- private val mDreamInTopComplicationsAnimDelay: Int,
+ private val mDreamInTopComplicationsAnimDelayMs: Long,
@Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
- private val mDreamInBottomComplicationsAnimDelay: Int
+ private val mDreamInBottomComplicationsAnimDelayMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DISTANCE)
+ private val mDreamOutTranslationYDistance: Int,
+ @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DURATION)
+ private val mDreamOutTranslationYDurationMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
+ private val mDreamOutTranslationYDelayBottomMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
+ private val mDreamOutTranslationYDelayTopMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DURATION) private val mDreamOutAlphaDurationMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_BOTTOM)
+ private val mDreamOutAlphaDelayBottomMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_TOP) private val mDreamOutAlphaDelayTopMs: Long,
+ @Named(DreamOverlayModule.DREAM_OUT_BLUR_DURATION) private val mDreamOutBlurDurationMs: Long
) {
- var mEntryAnimations: AnimatorSet? = null
+ private var mAnimator: Animator? = null
+
+ /**
+ * Store the current alphas at the various positions. This is so that we may resume an animation
+ * at the current alpha.
+ */
+ private var mCurrentAlphaAtPosition = mutableMapOf<Int, Float>()
+
+ @FloatRange(from = 0.0, to = 1.0) private var mBlurProgress: Float = 0f
/** Starts the dream content and dream overlay entry animations. */
- fun startEntryAnimations(view: View) {
- cancelRunningEntryAnimations()
+ @JvmOverloads
+ fun startEntryAnimations(view: View, animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
+ cancelAnimations()
- mEntryAnimations = AnimatorSet()
- mEntryAnimations?.apply {
- playTogether(
- buildDreamInBlurAnimator(view),
- buildDreamInTopComplicationsAnimator(),
- buildDreamInBottomComplicationsAnimator()
- )
- doOnEnd { mOverlayStateController.setEntryAnimationsFinished(true) }
- start()
- }
+ mAnimator =
+ animatorBuilder().apply {
+ playTogether(
+ blurAnimator(
+ view = view,
+ from = 1f,
+ to = 0f,
+ durationMs = mDreamInBlurAnimDurationMs,
+ delayMs = mDreamInBlurAnimDelayMs
+ ),
+ alphaAnimator(
+ from = 0f,
+ to = 1f,
+ durationMs = mDreamInComplicationsAnimDurationMs,
+ delayMs = mDreamInTopComplicationsAnimDelayMs,
+ position = ComplicationLayoutParams.POSITION_TOP
+ ),
+ alphaAnimator(
+ from = 0f,
+ to = 1f,
+ durationMs = mDreamInComplicationsAnimDurationMs,
+ delayMs = mDreamInBottomComplicationsAnimDelayMs,
+ position = ComplicationLayoutParams.POSITION_BOTTOM
+ )
+ )
+ doOnEnd {
+ mAnimator = null
+ mOverlayStateController.setEntryAnimationsFinished(true)
+ }
+ start()
+ }
+ }
+
+ /** Starts the dream content and dream overlay exit animations. */
+ @JvmOverloads
+ fun startExitAnimations(
+ view: View,
+ doneCallback: () -> Unit,
+ animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
+ ) {
+ cancelAnimations()
+
+ mAnimator =
+ animatorBuilder().apply {
+ playTogether(
+ blurAnimator(
+ view = view,
+ // Start the blurring wherever the entry animation ended, in
+ // case it was cancelled early.
+ from = mBlurProgress,
+ to = 1f,
+ durationMs = mDreamOutBlurDurationMs
+ ),
+ translationYAnimator(
+ from = 0f,
+ to = mDreamOutTranslationYDistance.toFloat(),
+ durationMs = mDreamOutTranslationYDurationMs,
+ delayMs = mDreamOutTranslationYDelayBottomMs,
+ position = ComplicationLayoutParams.POSITION_BOTTOM,
+ animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
+ ),
+ translationYAnimator(
+ from = 0f,
+ to = mDreamOutTranslationYDistance.toFloat(),
+ durationMs = mDreamOutTranslationYDurationMs,
+ delayMs = mDreamOutTranslationYDelayTopMs,
+ position = ComplicationLayoutParams.POSITION_TOP,
+ animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
+ ),
+ alphaAnimator(
+ from =
+ mCurrentAlphaAtPosition.getOrDefault(
+ key = ComplicationLayoutParams.POSITION_BOTTOM,
+ defaultValue = 1f
+ ),
+ to = 0f,
+ durationMs = mDreamOutAlphaDurationMs,
+ delayMs = mDreamOutAlphaDelayBottomMs,
+ position = ComplicationLayoutParams.POSITION_BOTTOM
+ ),
+ alphaAnimator(
+ from =
+ mCurrentAlphaAtPosition.getOrDefault(
+ key = ComplicationLayoutParams.POSITION_TOP,
+ defaultValue = 1f
+ ),
+ to = 0f,
+ durationMs = mDreamOutAlphaDurationMs,
+ delayMs = mDreamOutAlphaDelayTopMs,
+ position = ComplicationLayoutParams.POSITION_TOP
+ )
+ )
+ doOnEnd {
+ mAnimator = null
+ mOverlayStateController.setExitAnimationsRunning(false)
+ doneCallback()
+ }
+ start()
+ }
+ mOverlayStateController.setExitAnimationsRunning(true)
}
/** Cancels the dream content and dream overlay animations, if they're currently running. */
- fun cancelRunningEntryAnimations() {
- if (mEntryAnimations?.isRunning == true) {
- mEntryAnimations?.cancel()
- }
- mEntryAnimations = null
+ fun cancelAnimations() {
+ mAnimator =
+ mAnimator?.let {
+ it.cancel()
+ null
+ }
}
- private fun buildDreamInBlurAnimator(view: View): Animator {
- return ValueAnimator.ofFloat(1f, 0f).apply {
- duration = mDreamInBlurAnimDuration.toLong()
- startDelay = mDreamInBlurAnimDelay.toLong()
+ private fun blurAnimator(
+ view: View,
+ from: Float,
+ to: Float,
+ durationMs: Long,
+ delayMs: Long = 0
+ ): Animator {
+ return ValueAnimator.ofFloat(from, to).apply {
+ duration = durationMs
+ startDelay = delayMs
interpolator = Interpolators.LINEAR
addUpdateListener { animator: ValueAnimator ->
+ mBlurProgress = animator.animatedValue as Float
mBlurUtils.applyBlur(
- view.viewRootImpl,
- mBlurUtils.blurRadiusOfRatio(animator.animatedValue as Float).toInt(),
- false /*opaque*/
+ viewRootImpl = view.viewRootImpl,
+ radius = mBlurUtils.blurRadiusOfRatio(mBlurProgress).toInt(),
+ opaque = false
)
}
}
}
- private fun buildDreamInTopComplicationsAnimator(): Animator {
- return ValueAnimator.ofFloat(0f, 1f).apply {
- duration = mDreamInComplicationsAnimDuration.toLong()
- startDelay = mDreamInTopComplicationsAnimDelay.toLong()
+ private fun alphaAnimator(
+ from: Float,
+ to: Float,
+ durationMs: Long,
+ delayMs: Long,
+ @Position position: Int
+ ): Animator {
+ return ValueAnimator.ofFloat(from, to).apply {
+ duration = durationMs
+ startDelay = delayMs
interpolator = Interpolators.LINEAR
addUpdateListener { va: ValueAnimator ->
- setTopElementsAlpha(va.animatedValue as Float)
+ setElementsAlphaAtPosition(
+ alpha = va.animatedValue as Float,
+ position = position,
+ fadingOut = to < from
+ )
}
}
}
- private fun buildDreamInBottomComplicationsAnimator(): Animator {
- return ValueAnimator.ofFloat(0f, 1f).apply {
- duration = mDreamInComplicationsAnimDuration.toLong()
- startDelay = mDreamInBottomComplicationsAnimDelay.toLong()
- interpolator = Interpolators.LINEAR
+ private fun translationYAnimator(
+ from: Float,
+ to: Float,
+ durationMs: Long,
+ delayMs: Long,
+ @Position position: Int,
+ animInterpolator: Interpolator
+ ): Animator {
+ return ValueAnimator.ofFloat(from, to).apply {
+ duration = durationMs
+ startDelay = delayMs
+ interpolator = animInterpolator
addUpdateListener { va: ValueAnimator ->
- setBottomElementsAlpha(va.animatedValue as Float)
+ setElementsTranslationYAtPosition(va.animatedValue as Float, position)
}
- addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationStart(animation: Animator) {
- mComplicationHostViewController
- .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
- .forEach(Consumer { v: View -> v.visibility = View.VISIBLE })
- }
- }
- )
}
}
- /** Sets alpha of top complications and the status bar. */
- private fun setTopElementsAlpha(alpha: Float) {
- mComplicationHostViewController
- .getViewsAtPosition(ComplicationLayoutParams.POSITION_TOP)
- .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
- mStatusBarViewController.setAlpha(alpha)
- }
-
- /** Sets alpha of bottom complications. */
- private fun setBottomElementsAlpha(alpha: Float) {
- mComplicationHostViewController
- .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
- .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
- }
-
- private fun setAlphaAndEnsureVisible(view: View, alpha: Float) {
- if (alpha > 0 && view.visibility != View.VISIBLE) {
- view.visibility = View.VISIBLE
+ /** Sets alpha of complications at the specified position. */
+ private fun setElementsAlphaAtPosition(alpha: Float, position: Int, fadingOut: Boolean) {
+ mCurrentAlphaAtPosition[position] = alpha
+ mComplicationHostViewController.getViewsAtPosition(position).forEach { view ->
+ if (fadingOut) {
+ CrossFadeHelper.fadeOut(view, 1 - alpha, /* remap= */ false)
+ } else {
+ CrossFadeHelper.fadeIn(view, alpha, /* remap= */ false)
+ }
}
+ if (position == ComplicationLayoutParams.POSITION_TOP) {
+ mStatusBarViewController.setFadeAmount(alpha, fadingOut)
+ }
+ }
- view.alpha = alpha
+ /** Sets y translation of complications at the specified position. */
+ private fun setElementsTranslationYAtPosition(translationY: Float, position: Int) {
+ mComplicationHostViewController.getViewsAtPosition(position).forEach { v ->
+ v.translationY = translationY
+ }
+ if (position == ComplicationLayoutParams.POSITION_TOP) {
+ mStatusBarViewController.setTranslationY(translationY)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 5c6d248..9d7ad30 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -29,6 +29,8 @@
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.NonNull;
+
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.dagger.qualifiers.Main;
@@ -42,6 +44,7 @@
import com.android.systemui.util.ViewController;
import java.util.Arrays;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
@@ -194,7 +197,7 @@
}
mPrimaryBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
- mDreamOverlayAnimationsController.cancelRunningEntryAnimations();
+ mDreamOverlayAnimationsController.cancelAnimations();
}
View getContainerView() {
@@ -251,4 +254,17 @@
: aboutToShowBouncerProgress(expansion + 0.03f));
return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction);
}
+
+ /**
+ * Handle the dream waking up and run any necessary animations.
+ *
+ * @param onAnimationEnd Callback to trigger once animations are finished.
+ * @param callbackExecutor Executor to execute the callback on.
+ */
+ public void wakeUp(@NonNull Runnable onAnimationEnd, @NonNull Executor callbackExecutor) {
+ mDreamOverlayAnimationsController.startExitAnimations(mView, () -> {
+ callbackExecutor.execute(onAnimationEnd);
+ return null;
+ });
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 8542412..e76d5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -213,6 +213,15 @@
mLifecycleRegistry.setCurrentState(state);
}
+ @Override
+ public void onWakeUp(@NonNull Runnable onCompletedCallback) {
+ mExecutor.execute(() -> {
+ if (mDreamOverlayContainerViewController != null) {
+ mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
+ }
+ });
+ }
+
/**
* Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
* called from the main executing thread. The window attributes closely mirror those that are
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index e80d0be..5f942b6 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -52,6 +52,7 @@
public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
public static final int STATE_DREAM_ENTRY_ANIMATIONS_FINISHED = 1 << 2;
+ public static final int STATE_DREAM_EXIT_ANIMATIONS_RUNNING = 1 << 3;
private static final int OP_CLEAR_STATE = 1;
private static final int OP_SET_STATE = 2;
@@ -211,6 +212,14 @@
return containsState(STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
}
+ /**
+ * Returns whether the dream content and dream overlay exit animations are running.
+ * @return {@code true} if animations are running, {@code false} otherwise.
+ */
+ public boolean areExitAnimationsRunning() {
+ return containsState(STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
+ }
+
private boolean containsState(int state) {
return (mState & state) != 0;
}
@@ -257,6 +266,15 @@
}
/**
+ * Sets whether dream content and dream overlay exit animations are running.
+ * @param running {@code true} if exit animations are running, {@code false} otherwise.
+ */
+ public void setExitAnimationsRunning(boolean running) {
+ modifyState(running ? OP_SET_STATE : OP_CLEAR_STATE,
+ STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
+ }
+
+ /**
* Returns the available complication types.
*/
@Complication.ComplicationType
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index d17fbe3..f1bb156 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -37,6 +37,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -217,18 +218,29 @@
}
/**
- * Sets alpha of the dream overlay status bar.
+ * Sets fade of the dream overlay status bar.
*
* No-op if the dream overlay status bar should not be shown.
*/
- protected void setAlpha(float alpha) {
+ protected void setFadeAmount(float fadeAmount, boolean fadingOut) {
updateVisibility();
if (mView.getVisibility() != View.VISIBLE) {
return;
}
- mView.setAlpha(alpha);
+ if (fadingOut) {
+ CrossFadeHelper.fadeOut(mView, 1 - fadeAmount, /* remap= */ false);
+ } else {
+ CrossFadeHelper.fadeIn(mView, fadeAmount, /* remap= */ false);
+ }
+ }
+
+ /**
+ * Sets the y translation of the dream overlay status bar.
+ */
+ public void setTranslationY(float translationY) {
+ mView.setTranslationY(translationY);
}
private boolean shouldShowStatusBar() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
index 41f5578..b07efdf 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
@@ -197,11 +197,11 @@
*/
interface VisibilityController {
/**
- * Called to set the visibility of all shown and future complications.
+ * Called to set the visibility of all shown and future complications. Changes in visibility
+ * will always be animated.
* @param visibility The desired future visibility.
- * @param animate whether the change should be animated.
*/
- void setVisibility(@View.Visibility int visibility, boolean animate);
+ void setVisibility(@View.Visibility int visibility);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
index 440dcbc..48159ae 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
@@ -21,12 +21,9 @@
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATION_MARGIN_DEFAULT;
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.SCOPED_COMPLICATIONS_LAYOUT;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.Constraints;
@@ -34,6 +31,7 @@
import com.android.systemui.R;
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.touch.TouchInsetManager;
import java.util.ArrayList;
@@ -481,7 +479,6 @@
private final TouchInsetManager.TouchInsetSession mSession;
private final int mFadeInDuration;
private final int mFadeOutDuration;
- private ViewPropertyAnimator mViewPropertyAnimator;
/** */
@Inject
@@ -498,26 +495,16 @@
}
@Override
- public void setVisibility(int visibility, boolean animate) {
- final boolean appearing = visibility == View.VISIBLE;
-
- if (mViewPropertyAnimator != null) {
- mViewPropertyAnimator.cancel();
+ public void setVisibility(int visibility) {
+ if (visibility == View.VISIBLE) {
+ CrossFadeHelper.fadeIn(mLayout, mFadeInDuration, /* delay= */ 0);
+ } else {
+ CrossFadeHelper.fadeOut(
+ mLayout,
+ mFadeOutDuration,
+ /* delay= */ 0,
+ /* endRunnable= */ null);
}
-
- if (appearing) {
- mLayout.setVisibility(View.VISIBLE);
- }
-
- mViewPropertyAnimator = mLayout.animate()
- .alpha(appearing ? 1f : 0f)
- .setDuration(appearing ? mFadeInDuration : mFadeOutDuration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLayout.setVisibility(visibility);
- }
- });
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
index 2b32d34..4fae68d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
@@ -38,7 +38,7 @@
POSITION_START,
})
- @interface Position {}
+ public @interface Position {}
/** Align view with the top of parent or bottom of preceding {@link Complication}. */
public static final int POSITION_TOP = 1 << 0;
/** Align view with the bottom of parent or top of preceding {@link Complication}. */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
index c9fecc9..09cc7c5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationHostViewModule.java
@@ -41,6 +41,7 @@
public static final String COMPLICATIONS_FADE_OUT_DURATION = "complications_fade_out_duration";
public static final String COMPLICATIONS_FADE_IN_DURATION = "complications_fade_in_duration";
public static final String COMPLICATIONS_RESTORE_TIMEOUT = "complication_restore_timeout";
+ public static final String COMPLICATIONS_FADE_OUT_DELAY = "complication_fade_out_delay";
/**
* Generates a {@link ConstraintLayout}, which can host
@@ -75,6 +76,16 @@
}
/**
+ * Provides the delay to wait for before fading out complications.
+ */
+ @Provides
+ @Named(COMPLICATIONS_FADE_OUT_DELAY)
+ @DreamOverlayComponent.DreamOverlayScope
+ static int providesComplicationsFadeOutDelay(@Main Resources resources) {
+ return resources.getInteger(R.integer.complicationFadeOutDelayMs);
+ }
+
+ /**
* Provides the fade in duration for complications.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index cb012fa..ed0e1d9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -55,6 +55,22 @@
"dream_in_top_complications_anim_delay";
public static final String DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY =
"dream_in_bottom_complications_anim_delay";
+ public static final String DREAM_OUT_TRANSLATION_Y_DISTANCE =
+ "dream_out_complications_translation_y";
+ public static final String DREAM_OUT_TRANSLATION_Y_DURATION =
+ "dream_out_complications_translation_y_duration";
+ public static final String DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM =
+ "dream_out_complications_translation_y_delay_bottom";
+ public static final String DREAM_OUT_TRANSLATION_Y_DELAY_TOP =
+ "dream_out_complications_translation_y_delay_top";
+ public static final String DREAM_OUT_ALPHA_DURATION =
+ "dream_out_complications_alpha_duration";
+ public static final String DREAM_OUT_ALPHA_DELAY_BOTTOM =
+ "dream_out_complications_alpha_delay_bottom";
+ public static final String DREAM_OUT_ALPHA_DELAY_TOP =
+ "dream_out_complications_alpha_delay_top";
+ public static final String DREAM_OUT_BLUR_DURATION =
+ "dream_out_blur_duration";
/** */
@Provides
@@ -127,8 +143,8 @@
*/
@Provides
@Named(DREAM_IN_BLUR_ANIMATION_DURATION)
- static int providesDreamInBlurAnimationDuration(@Main Resources resources) {
- return resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
+ static long providesDreamInBlurAnimationDuration(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
}
/**
@@ -136,8 +152,8 @@
*/
@Provides
@Named(DREAM_IN_BLUR_ANIMATION_DELAY)
- static int providesDreamInBlurAnimationDelay(@Main Resources resources) {
- return resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
+ static long providesDreamInBlurAnimationDelay(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
}
/**
@@ -145,8 +161,8 @@
*/
@Provides
@Named(DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
- static int providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
- return resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
+ static long providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
}
/**
@@ -154,8 +170,8 @@
*/
@Provides
@Named(DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
- static int providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
- return resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
+ static long providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
}
/**
@@ -163,8 +179,69 @@
*/
@Provides
@Named(DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
- static int providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
- return resources.getInteger(R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
+ static long providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
+ return (long) resources.getInteger(
+ R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
+ }
+
+ /**
+ * Provides the number of pixels to translate complications when waking up from dream.
+ */
+ @Provides
+ @Named(DREAM_OUT_TRANSLATION_Y_DISTANCE)
+ @DreamOverlayComponent.DreamOverlayScope
+ static int providesDreamOutComplicationsTranslationY(@Main Resources resources) {
+ return resources.getDimensionPixelSize(R.dimen.dream_overlay_exit_y_offset);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_TRANSLATION_Y_DURATION)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsTranslationYDuration(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDurationMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsTranslationYDelayBottom(@Main Resources resources) {
+ return (long) resources.getInteger(
+ R.integer.config_dreamOverlayOutTranslationYDelayBottomMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsTranslationYDelayTop(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDelayTopMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_ALPHA_DURATION)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsAlphaDuration(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDurationMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_ALPHA_DELAY_BOTTOM)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsAlphaDelayBottom(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayBottomMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_ALPHA_DELAY_TOP)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutComplicationsAlphaDelayTop(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayTopMs);
+ }
+
+ @Provides
+ @Named(DREAM_OUT_BLUR_DURATION)
+ @DreamOverlayComponent.DreamOverlayScope
+ static long providesDreamOutBlurDuration(@Main Resources resources) {
+ return (long) resources.getInteger(R.integer.config_dreamOverlayOutBlurDurationMs);
}
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
index 3087cdf..e276e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/HideComplicationTouchHandler.java
@@ -16,22 +16,26 @@
package com.android.systemui.dreams.touch;
+import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_FADE_OUT_DELAY;
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_RESTORE_TIMEOUT;
-import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.touch.TouchInsetManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import com.google.common.util.concurrent.ListenableFuture;
+import java.util.ArrayDeque;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
@@ -49,33 +53,58 @@
private static final String TAG = "HideComplicationHandler";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private final Complication.VisibilityController mVisibilityController;
private final int mRestoreTimeout;
+ private final int mFadeOutDelay;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private final Handler mHandler;
- private final Executor mExecutor;
+ private final DelayableExecutor mExecutor;
+ private final DreamOverlayStateController mOverlayStateController;
private final TouchInsetManager mTouchInsetManager;
+ private final Complication.VisibilityController mVisibilityController;
+ private boolean mHidden = false;
+ @Nullable
+ private Runnable mHiddenCallback;
+ private final ArrayDeque<Runnable> mCancelCallbacks = new ArrayDeque<>();
+
private final Runnable mRestoreComplications = new Runnable() {
@Override
public void run() {
- mVisibilityController.setVisibility(View.VISIBLE, true);
+ mVisibilityController.setVisibility(View.VISIBLE);
+ mHidden = false;
+ }
+ };
+
+ private final Runnable mHideComplications = new Runnable() {
+ @Override
+ public void run() {
+ if (mOverlayStateController.areExitAnimationsRunning()) {
+ // Avoid interfering with the exit animations.
+ return;
+ }
+ mVisibilityController.setVisibility(View.INVISIBLE);
+ mHidden = true;
+ if (mHiddenCallback != null) {
+ mHiddenCallback.run();
+ mHiddenCallback = null;
+ }
}
};
@Inject
HideComplicationTouchHandler(Complication.VisibilityController visibilityController,
@Named(COMPLICATIONS_RESTORE_TIMEOUT) int restoreTimeout,
+ @Named(COMPLICATIONS_FADE_OUT_DELAY) int fadeOutDelay,
TouchInsetManager touchInsetManager,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- @Main Executor executor,
- @Main Handler handler) {
+ @Main DelayableExecutor executor,
+ DreamOverlayStateController overlayStateController) {
mVisibilityController = visibilityController;
mRestoreTimeout = restoreTimeout;
+ mFadeOutDelay = fadeOutDelay;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
- mHandler = handler;
mTouchInsetManager = touchInsetManager;
mExecutor = executor;
+ mOverlayStateController = overlayStateController;
}
@Override
@@ -87,7 +116,8 @@
final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
// If other sessions are interested in this touch, do not fade out elements.
- if (session.getActiveSessionCount() > 1 || bouncerShowing) {
+ if (session.getActiveSessionCount() > 1 || bouncerShowing
+ || mOverlayStateController.areExitAnimationsRunning()) {
if (DEBUG) {
Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount()
+ ". Bouncer showing: " + bouncerShowing);
@@ -115,8 +145,11 @@
touchCheck.addListener(() -> {
try {
if (!touchCheck.get()) {
- mHandler.removeCallbacks(mRestoreComplications);
- mVisibilityController.setVisibility(View.INVISIBLE, true);
+ // Cancel all pending callbacks.
+ while (!mCancelCallbacks.isEmpty()) mCancelCallbacks.pop().run();
+ mCancelCallbacks.add(
+ mExecutor.executeDelayed(
+ mHideComplications, mFadeOutDelay));
} else {
// If a touch occurred inside the dream overlay touch insets, do not
// handle the touch.
@@ -130,7 +163,23 @@
|| motionEvent.getAction() == MotionEvent.ACTION_UP) {
// End session and initiate delayed reappearance of the complications.
session.pop();
- mHandler.postDelayed(mRestoreComplications, mRestoreTimeout);
+ runAfterHidden(() -> mCancelCallbacks.add(
+ mExecutor.executeDelayed(mRestoreComplications,
+ mRestoreTimeout)));
+ }
+ });
+ }
+
+ /**
+ * Triggers a runnable after complications have been hidden. Will override any previously set
+ * runnable currently waiting for hide to happen.
+ */
+ private void runAfterHidden(Runnable runnable) {
+ mExecutor.execute(() -> {
+ if (mHidden) {
+ runnable.run();
+ } else {
+ mHiddenCallback = runnable;
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 2dbbb1b..784e92d 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -290,7 +290,7 @@
@Keep
@JvmField
val WM_ENABLE_SHELL_TRANSITIONS =
- sysPropBooleanFlag(1100, "persist.wm.debug.shell_transit", default = true)
+ sysPropBooleanFlag(1100, "persist.wm.debug.shell_transit", default = false)
// TODO(b/254513207): Tracking Bug
@Keep
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
index 18fb423..d9bcb50 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
@@ -50,13 +50,12 @@
@Override
public void accept(T extension) {
- try {
- Fragment.class.cast(extension);
+ if (Fragment.class.isInstance(extension)) {
mFragmentHostManager.getExtensionManager().setCurrentExtension(mId, mTag,
mOldClass, extension.getClass().getName(), mExtension.getContext());
mOldClass = extension.getClass().getName();
- } catch (ClassCastException e) {
- Log.e(TAG, extension.getClass().getName() + " must be a Fragment", e);
+ } else {
+ Log.e(TAG, extension.getClass().getName() + " must be a Fragment");
}
mExtension.clearItem(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 663582e..3d976d4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -410,6 +410,11 @@
private final int mDreamOpenAnimationDuration;
/**
+ * The duration in milliseconds of the dream close animation.
+ */
+ private final int mDreamCloseAnimationDuration;
+
+ /**
* The animation used for hiding keyguard. This is used to fetch the animation timings if
* WindowManager is not providing us with them.
*/
@@ -1056,7 +1061,8 @@
}
mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
- mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
+ mUnoccludeAnimator.setDuration(isDream ? mDreamCloseAnimationDuration
+ : UNOCCLUDE_ANIMATION_DURATION);
mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
mUnoccludeAnimator.addUpdateListener(
animation -> {
@@ -1208,6 +1214,8 @@
mDreamOpenAnimationDuration = context.getResources().getInteger(
com.android.internal.R.integer.config_dreamOpenAnimationDuration);
+ mDreamCloseAnimationDuration = context.getResources().getInteger(
+ com.android.internal.R.integer.config_dreamCloseAnimationDuration);
}
public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index be82b1f..67e9664 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -1096,7 +1096,7 @@
Pair<Integer, Integer> first = emojiIndices.get(i - 1);
// Check if second emoji starts right after first starts
- if (second.first == first.second) {
+ if (Objects.equals(second.first, first.second)) {
// Check if emojis in sequence are the same
if (Objects.equals(emojiTexts.get(i), emojiTexts.get(i - 1))) {
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 815b86e..cd13085 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -132,8 +132,11 @@
mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
- setLayoutParams(layoutParams);
+ final int newShelfHeight = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
+ if (newShelfHeight != layoutParams.height) {
+ layoutParams.height = newShelfHeight;
+ setLayoutParams(layoutParams);
+ }
final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
mShelfIcons.setPadding(padding, 0, padding, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 5873837..6bd9502 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -235,19 +235,24 @@
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
- activityStarter.startActivity(
- intent,
- true, /* dismissShade */
- null, /* launch animator - looks bad with the transparent smartspace bg */
- showOnLockscreen
- )
+ if (showOnLockscreen) {
+ activityStarter.startActivity(
+ intent,
+ true, /* dismissShade */
+ // launch animator - looks bad with the transparent smartspace bg
+ null,
+ true
+ )
+ } else {
+ activityStarter.postStartActivityDismissingKeyguard(intent, 0)
+ }
}
override fun startPendingIntent(pi: PendingIntent, showOnLockscreen: Boolean) {
if (showOnLockscreen) {
pi.send()
} else {
- activityStarter.startPendingIntentDismissingKeyguard(pi)
+ activityStarter.postStartActivityDismissingKeyguard(pi)
}
}
})
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 58f59be..5f6a5cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -53,6 +53,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -534,7 +535,7 @@
return;
}
if (loggedExpansionState != null
- && state.mIsExpanded == loggedExpansionState) {
+ && Objects.equals(state.mIsExpanded, loggedExpansionState)) {
return;
}
mLoggedExpansionState.put(key, state.mIsExpanded);
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
index ad09ee3..e137107 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt
@@ -133,7 +133,9 @@
launch {
viewModel.users.collect { users ->
val viewPool =
- view.children.filter { it.tag == USER_VIEW_TAG }.toMutableList()
+ gridContainerView.children
+ .filter { it.tag == USER_VIEW_TAG }
+ .toMutableList()
viewPool.forEach {
gridContainerView.removeView(it)
flowWidget.removeView(it)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
new file mode 100644
index 0000000..99406ed
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -0,0 +1,125 @@
+package com.android.systemui.dreams
+
+import android.animation.Animator
+import android.animation.AnimatorSet
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dreams.complication.ComplicationHostViewController
+import com.android.systemui.statusbar.BlurUtils
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
+
+ companion object {
+ private const val DREAM_IN_BLUR_ANIMATION_DURATION = 1L
+ private const val DREAM_IN_BLUR_ANIMATION_DELAY = 2L
+ private const val DREAM_IN_COMPLICATIONS_ANIMATION_DURATION = 3L
+ private const val DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY = 4L
+ private const val DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY = 5L
+ private const val DREAM_OUT_TRANSLATION_Y_DISTANCE = 6
+ private const val DREAM_OUT_TRANSLATION_Y_DURATION = 7L
+ private const val DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM = 8L
+ private const val DREAM_OUT_TRANSLATION_Y_DELAY_TOP = 9L
+ private const val DREAM_OUT_ALPHA_DURATION = 10L
+ private const val DREAM_OUT_ALPHA_DELAY_BOTTOM = 11L
+ private const val DREAM_OUT_ALPHA_DELAY_TOP = 12L
+ private const val DREAM_OUT_BLUR_DURATION = 13L
+ }
+
+ @Mock private lateinit var mockAnimator: AnimatorSet
+ @Mock private lateinit var blurUtils: BlurUtils
+ @Mock private lateinit var hostViewController: ComplicationHostViewController
+ @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController
+ @Mock private lateinit var stateController: DreamOverlayStateController
+ private lateinit var controller: DreamOverlayAnimationsController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ controller =
+ DreamOverlayAnimationsController(
+ blurUtils,
+ hostViewController,
+ statusBarViewController,
+ stateController,
+ DREAM_IN_BLUR_ANIMATION_DURATION,
+ DREAM_IN_BLUR_ANIMATION_DELAY,
+ DREAM_IN_COMPLICATIONS_ANIMATION_DURATION,
+ DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY,
+ DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY,
+ DREAM_OUT_TRANSLATION_Y_DISTANCE,
+ DREAM_OUT_TRANSLATION_Y_DURATION,
+ DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM,
+ DREAM_OUT_TRANSLATION_Y_DELAY_TOP,
+ DREAM_OUT_ALPHA_DURATION,
+ DREAM_OUT_ALPHA_DELAY_BOTTOM,
+ DREAM_OUT_ALPHA_DELAY_TOP,
+ DREAM_OUT_BLUR_DURATION
+ )
+ }
+
+ @Test
+ fun testExitAnimationOnEnd() {
+ val mockCallback: () -> Unit = mock()
+
+ controller.startExitAnimations(
+ view = mock(),
+ doneCallback = mockCallback,
+ animatorBuilder = { mockAnimator }
+ )
+
+ val captor = argumentCaptor<Animator.AnimatorListener>()
+ verify(mockAnimator).addListener(captor.capture())
+ val listener = captor.value
+
+ verify(mockCallback, never()).invoke()
+ listener.onAnimationEnd(mockAnimator)
+ verify(mockCallback, times(1)).invoke()
+ }
+
+ @Test
+ fun testCancellation() {
+ controller.startExitAnimations(
+ view = mock(),
+ doneCallback = mock(),
+ animatorBuilder = { mockAnimator }
+ )
+
+ verify(mockAnimator, never()).cancel()
+ controller.cancelAnimations()
+ verify(mockAnimator, times(1)).cancel()
+ }
+
+ @Test
+ fun testExitAfterStartWillCancel() {
+ val mockStartAnimator: AnimatorSet = mock()
+ val mockExitAnimator: AnimatorSet = mock()
+
+ controller.startEntryAnimations(view = mock(), animatorBuilder = { mockStartAnimator })
+
+ verify(mockStartAnimator, never()).cancel()
+
+ controller.startExitAnimations(
+ view = mock(),
+ doneCallback = mock(),
+ animatorBuilder = { mockExitAnimator }
+ )
+
+ // Verify that we cancelled the start animator in favor of the exit
+ // animator.
+ verify(mockStartAnimator, times(1)).cancel()
+ verify(mockExitAnimator, never()).cancel()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 517804d..73c226d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -204,7 +204,7 @@
mController.onViewAttached();
verify(mAnimationsController).startEntryAnimations(mDreamOverlayContainerView);
- verify(mAnimationsController, never()).cancelRunningEntryAnimations();
+ verify(mAnimationsController, never()).cancelAnimations();
}
@Test
@@ -221,6 +221,6 @@
mController.onViewAttached();
mController.onViewDetached();
- verify(mAnimationsController).cancelRunningEntryAnimations();
+ verify(mAnimationsController).cancelAnimations();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index f04a37f..ffb8342 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -337,4 +338,28 @@
verify(mDreamOverlayComponent).getDreamOverlayContainerViewController();
verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor();
}
+
+ @Test
+ public void testWakeUp() throws RemoteException {
+ final IBinder proxy = mService.onBind(new Intent());
+ final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
+
+ // Inform the overlay service of dream starting.
+ overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
+ true /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
+
+ final Runnable callback = mock(Runnable.class);
+ mService.onWakeUp(callback);
+ mMainExecutor.runAllReady();
+ verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
+ }
+
+ @Test
+ public void testWakeUpBeforeStartDoesNothing() {
+ final Runnable callback = mock(Runnable.class);
+ mService.onWakeUp(callback);
+ mMainExecutor.runAllReady();
+ verify(mDreamOverlayContainerViewController, never()).wakeUp(callback, mMainExecutor);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
index 14a5702..4e3aca7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/HideComplicationTouchHandlerTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.dreams.touch;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -33,6 +31,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -52,6 +51,7 @@
@RunWith(AndroidTestingRunner.class)
public class HideComplicationTouchHandlerTest extends SysuiTestCase {
private static final int RESTORE_TIMEOUT = 1000;
+ private static final int HIDE_DELAY = 500;
@Mock
Complication.VisibilityController mVisibilityController;
@@ -71,11 +71,18 @@
@Mock
DreamTouchHandler.TouchSession mSession;
- FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
+ @Mock
+ DreamOverlayStateController mStateController;
+
+ FakeSystemClock mClock;
+
+ FakeExecutor mFakeExecutor;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mClock = new FakeSystemClock();
+ mFakeExecutor = new FakeExecutor(mClock);
}
/**
@@ -86,10 +93,11 @@
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
mVisibilityController,
RESTORE_TIMEOUT,
+ HIDE_DELAY,
mTouchInsetManager,
mStatusBarKeyguardViewManager,
mFakeExecutor,
- mHandler);
+ mStateController);
// Report multiple active sessions.
when(mSession.getActiveSessionCount()).thenReturn(2);
@@ -103,8 +111,10 @@
// Verify session end.
verify(mSession).pop();
+ mClock.advanceTime(HIDE_DELAY);
+
// Verify no interaction with visibility controller.
- verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+ verify(mVisibilityController, never()).setVisibility(anyInt());
}
/**
@@ -115,10 +125,11 @@
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
mVisibilityController,
RESTORE_TIMEOUT,
+ HIDE_DELAY,
mTouchInsetManager,
mStatusBarKeyguardViewManager,
mFakeExecutor,
- mHandler);
+ mStateController);
// Report one session.
when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -132,8 +143,10 @@
// Verify session end.
verify(mSession).pop();
+ mClock.advanceTime(HIDE_DELAY);
+
// Verify no interaction with visibility controller.
- verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+ verify(mVisibilityController, never()).setVisibility(anyInt());
}
/**
@@ -144,10 +157,11 @@
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
mVisibilityController,
RESTORE_TIMEOUT,
+ HIDE_DELAY,
mTouchInsetManager,
mStatusBarKeyguardViewManager,
mFakeExecutor,
- mHandler);
+ mStateController);
// Report one session
when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -177,8 +191,10 @@
// Verify session ended.
verify(mSession).pop();
+ mClock.advanceTime(HIDE_DELAY);
+
// Verify no interaction with visibility controller.
- verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
+ verify(mVisibilityController, never()).setVisibility(anyInt());
}
/**
@@ -189,10 +205,11 @@
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
mVisibilityController,
RESTORE_TIMEOUT,
+ HIDE_DELAY,
mTouchInsetManager,
mStatusBarKeyguardViewManager,
mFakeExecutor,
- mHandler);
+ mStateController);
// Report one session
when(mSession.getActiveSessionCount()).thenReturn(1);
@@ -221,11 +238,11 @@
inputEventListenerCaptor.getValue().onInputEvent(mMotionEvent);
mFakeExecutor.runAllReady();
- // Verify callback to restore visibility cancelled.
- verify(mHandler).removeCallbacks(any());
-
+ // Verify visibility controller doesn't hide until after timeout
+ verify(mVisibilityController, never()).setVisibility(eq(View.INVISIBLE));
+ mClock.advanceTime(HIDE_DELAY);
// Verify visibility controller told to hide complications.
- verify(mVisibilityController).setVisibility(eq(View.INVISIBLE), anyBoolean());
+ verify(mVisibilityController).setVisibility(eq(View.INVISIBLE));
Mockito.clearInvocations(mVisibilityController, mHandler);
@@ -235,11 +252,8 @@
mFakeExecutor.runAllReady();
// Verify visibility controller told to show complications.
- ArgumentCaptor<Runnable> delayRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
- verify(mHandler).postDelayed(delayRunnableCaptor.capture(),
- eq(Long.valueOf(RESTORE_TIMEOUT)));
- delayRunnableCaptor.getValue().run();
- verify(mVisibilityController).setVisibility(eq(View.VISIBLE), anyBoolean());
+ mClock.advanceTime(RESTORE_TIMEOUT);
+ verify(mVisibilityController).setVisibility(eq(View.VISIBLE));
// Verify session ended.
verify(mSession).pop();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
index f4bc232..df3a62f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageExporterTest.java
@@ -75,7 +75,7 @@
private static final byte[] EXIF_FILE_TAG = "Exif\u0000\u0000".getBytes(US_ASCII);
private static final ZonedDateTime CAPTURE_TIME =
- ZonedDateTime.of(LocalDateTime.of(2020, 12, 15, 13, 15), ZoneId.of("EST"));
+ ZonedDateTime.of(LocalDateTime.of(2020, 12, 15, 13, 15), ZoneId.of("America/New_York"));
private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
@Mock
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 8525e36..592045c 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -245,6 +245,7 @@
});
}
+ @SuppressWarnings("ReturnValueIgnored")
private void maybeRequestShowInlineSuggestions(int sessionId,
@Nullable InlineSuggestionsRequest request,
@Nullable List<Dataset> inlineSuggestionsData, @Nullable Bundle clientState,
diff --git a/services/backup/java/com/android/server/backup/BackupAndRestoreFeatureFlags.java b/services/backup/java/com/android/server/backup/BackupAndRestoreFeatureFlags.java
new file mode 100644
index 0000000..042bcbd
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/BackupAndRestoreFeatureFlags.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup;
+
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.provider.DeviceConfig;
+
+/**
+ * Retrieves values of feature flags.
+ *
+ * <p>These flags are intended to be configured server-side and their values should be set in {@link
+ * DeviceConfig} by a service that periodically syncs with the server.
+ *
+ * <p>This class must ensure that the namespace, flag name, and default value passed into {@link
+ * DeviceConfig} matches what's declared on the server. The namespace is shared for all backup and
+ * restore flags.
+ */
+public class BackupAndRestoreFeatureFlags {
+ private static final String NAMESPACE = "backup_and_restore";
+
+ private BackupAndRestoreFeatureFlags() {}
+
+ /** Retrieves the value of the flag "backup_transport_future_timeout_millis". */
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+ public static long getBackupTransportFutureTimeoutMillis() {
+ return DeviceConfig.getLong(
+ NAMESPACE,
+ /* name= */ "backup_transport_future_timeout_millis",
+ /* defaultValue= */ 600000); // 10 minutes
+ }
+
+ /** Retrieves the value of the flag "backup_transport_callback_timeout_millis". */
+ @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
+ public static long getBackupTransportCallbackTimeoutMillis() {
+ return DeviceConfig.getLong(
+ NAMESPACE,
+ /* name= */ "backup_transport_callback_timeout_millis",
+ /* defaultValue= */ 300000); // 5 minutes
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/OperationStorage.java b/services/backup/java/com/android/server/backup/OperationStorage.java
index 466f647..8f73436 100644
--- a/services/backup/java/com/android/server/backup/OperationStorage.java
+++ b/services/backup/java/com/android/server/backup/OperationStorage.java
@@ -153,4 +153,4 @@
* @return a set of operation tokens for operations in that state.
*/
Set<Integer> operationTokensForOpState(@OpState int state);
-};
+}
diff --git a/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java b/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
index 6908c60..a94167e 100644
--- a/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
+++ b/services/backup/java/com/android/server/backup/internal/LifecycleOperationStorage.java
@@ -353,4 +353,4 @@
op.callback.handleCancel(cancelAll);
}
}
-};
+}
diff --git a/services/backup/java/com/android/server/backup/transport/BackupTransportClient.java b/services/backup/java/com/android/server/backup/transport/BackupTransportClient.java
index 40d7cad..21005bb 100644
--- a/services/backup/java/com/android/server/backup/transport/BackupTransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/BackupTransportClient.java
@@ -30,6 +30,7 @@
import com.android.internal.backup.IBackupTransport;
import com.android.internal.infra.AndroidFuture;
+import com.android.server.backup.BackupAndRestoreFeatureFlags;
import java.util.ArrayDeque;
import java.util.HashSet;
@@ -385,7 +386,8 @@
private <T> T getFutureResult(AndroidFuture<T> future) {
try {
- return future.get(600, TimeUnit.SECONDS);
+ return future.get(BackupAndRestoreFeatureFlags.getBackupTransportFutureTimeoutMillis(),
+ TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException
| CancellationException e) {
Slog.w(TAG, "Failed to get result from transport:", e);
diff --git a/services/backup/java/com/android/server/backup/transport/TransportStatusCallback.java b/services/backup/java/com/android/server/backup/transport/TransportStatusCallback.java
index fb98825..deaa86c 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportStatusCallback.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportStatusCallback.java
@@ -23,13 +23,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.ITransportStatusCallback;
+import com.android.server.backup.BackupAndRestoreFeatureFlags;
public class TransportStatusCallback extends ITransportStatusCallback.Stub {
private static final String TAG = "TransportStatusCallback";
- private static final int TIMEOUT_MILLIS = 300 * 1000; // 5 minutes.
private static final int OPERATION_STATUS_DEFAULT = 0;
- private final int mOperationTimeout;
+ private final long mOperationTimeout;
@GuardedBy("this")
private int mOperationStatus = OPERATION_STATUS_DEFAULT;
@@ -37,7 +37,7 @@
private boolean mHasCompletedOperation = false;
public TransportStatusCallback() {
- mOperationTimeout = TIMEOUT_MILLIS;
+ mOperationTimeout = BackupAndRestoreFeatureFlags.getBackupTransportCallbackTimeoutMillis();
}
@VisibleForTesting
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 0f101b0..08ee6d7 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -658,7 +658,6 @@
int sessionId, int flags, @NonNull IResultReceiver result) {
Objects.requireNonNull(activityToken);
Objects.requireNonNull(shareableActivityToken);
- Objects.requireNonNull(sessionId);
final int userId = UserHandle.getCallingUserId();
final ActivityPresentationInfo activityPresentationInfo = getAmInternal()
@@ -677,7 +676,6 @@
@Override
public void finishSession(int sessionId) {
- Objects.requireNonNull(sessionId);
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7fb3765..86bb699 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -23,18 +23,29 @@
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_DEPRECATED;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_DISABLED;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_OK;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE;
+import static android.app.ForegroundServiceTypePolicy.FGS_TYPE_POLICY_CHECK_UNKNOWN;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN;
import static android.os.PowerExemptionManager.REASON_ACTIVITY_STARTER;
import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD;
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
import static android.os.PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_CARRIER_PRIVILEGED_APP;
import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
import static android.os.PowerExemptionManager.REASON_CURRENT_INPUT_METHOD;
import static android.os.PowerExemptionManager.REASON_DENIED;
import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER;
+import static android.os.PowerExemptionManager.REASON_DISALLOW_APPS_CONTROL;
+import static android.os.PowerExemptionManager.REASON_DPO_PROTECTED_APP;
import static android.os.PowerExemptionManager.REASON_FGS_BINDING;
import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
@@ -45,10 +56,12 @@
import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
import static android.os.PowerExemptionManager.REASON_PROC_STATE_TOP;
import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
+import static android.os.PowerExemptionManager.REASON_ROLE_EMERGENCY;
import static android.os.PowerExemptionManager.REASON_SERVICE_LAUNCH;
import static android.os.PowerExemptionManager.REASON_START_ACTIVITY_FLAG;
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_MODULE;
import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE;
import static android.os.PowerExemptionManager.REASON_UID_VISIBLE;
@@ -63,6 +76,9 @@
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
import static com.android.internal.messages.nano.SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICE_BG_LAUNCH;
+import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED;
+import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER;
+import static com.android.internal.util.FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT;
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
import static com.android.internal.util.FrameworkStatsLog.SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT;
@@ -94,6 +110,11 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.ForegroundServiceStartNotAllowedException;
+import android.app.ForegroundServiceTypeNotAllowedException;
+import android.app.ForegroundServiceTypePolicy;
+import android.app.ForegroundServiceTypePolicy.ForegroundServicePolicyCheckCode;
+import android.app.ForegroundServiceTypePolicy.ForegroundServiceTypePermission;
+import android.app.ForegroundServiceTypePolicy.ForegroundServiceTypePolicyInfo;
import android.app.IApplicationThread;
import android.app.IForegroundServiceObserver;
import android.app.IServiceConnection;
@@ -122,6 +143,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -576,6 +598,7 @@
getAppStateTracker().addBackgroundRestrictedAppListener(new BackgroundRestrictedListener());
mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class);
setAllowListWhileInUsePermissionInFgs();
+ initSystemExemptedFgsTypePermission();
}
private AppStateTracker getAppStateTracker() {
@@ -757,8 +780,8 @@
Slog.w(TAG, msg);
showFgsBgRestrictedNotificationLocked(r);
logFGSStateChangeLocked(r,
- FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
- 0, FGS_STOP_REASON_UNKNOWN);
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
+ 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID, callingUid)) {
throw new ForegroundServiceStartNotAllowedException(msg);
}
@@ -1911,6 +1934,7 @@
ignoreForeground = true;
}
+ int fgsTypeCheckCode = FGS_TYPE_POLICY_CHECK_UNKNOWN;
if (!ignoreForeground) {
if (r.mStartForegroundCount == 0) {
/*
@@ -1969,13 +1993,49 @@
updateServiceForegroundLocked(psr, true);
ignoreForeground = true;
logFGSStateChangeLocked(r,
- FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
- 0, FGS_STOP_REASON_UNKNOWN);
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
+ 0, FGS_STOP_REASON_UNKNOWN, FGS_TYPE_POLICY_CHECK_UNKNOWN);
if (CompatChanges.isChangeEnabled(FGS_START_EXCEPTION_CHANGE_ID,
r.appInfo.uid)) {
throw new ForegroundServiceStartNotAllowedException(msg);
}
}
+
+ if (!ignoreForeground) {
+ Pair<Integer, RuntimeException> fgsTypeResult = null;
+ if (foregroundServiceType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+ fgsTypeResult = validateForegroundServiceType(r,
+ foregroundServiceType,
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
+ } else {
+ int fgsTypes = foregroundServiceType;
+ // If the service has declared some unknown types which might be coming
+ // from future releases, and if it also comes with the "specialUse",
+ // then it'll be deemed as the "specialUse" and we ignore this
+ // unknown type. Otherwise, it'll be treated as an invalid type.
+ int defaultFgsTypes = (foregroundServiceType
+ & ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE) != 0
+ ? ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
+ : ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
+ for (int serviceType = Integer.highestOneBit(fgsTypes);
+ serviceType != 0;
+ serviceType = Integer.highestOneBit(fgsTypes)) {
+ fgsTypeResult = validateForegroundServiceType(r,
+ serviceType, defaultFgsTypes);
+ fgsTypes &= ~serviceType;
+ if (fgsTypeResult.first != FGS_TYPE_POLICY_CHECK_OK) {
+ break;
+ }
+ }
+ }
+ fgsTypeCheckCode = fgsTypeResult.first;
+ if (fgsTypeResult.second != null) {
+ logFGSStateChangeLocked(r,
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED,
+ 0, FGS_STOP_REASON_UNKNOWN, fgsTypeResult.first);
+ throw fgsTypeResult.second;
+ }
+ }
}
// Apps under strict background restrictions simply don't get to have foreground
@@ -2044,8 +2104,8 @@
registerAppOpCallbackLocked(r);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
logFGSStateChangeLocked(r,
- FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
- 0, FGS_STOP_REASON_UNKNOWN);
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER,
+ 0, FGS_STOP_REASON_UNKNOWN, fgsTypeCheckCode);
updateNumForegroundServicesLocked();
}
// Even if the service is already a FGS, we need to update the notification,
@@ -2126,10 +2186,11 @@
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
unregisterAppOpCallbackLocked(r);
logFGSStateChangeLocked(r,
- FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
r.mFgsExitTime > r.mFgsEnterTime
? (int) (r.mFgsExitTime - r.mFgsEnterTime) : 0,
- FGS_STOP_REASON_STOP_FOREGROUND);
+ FGS_STOP_REASON_STOP_FOREGROUND,
+ FGS_TYPE_POLICY_CHECK_UNKNOWN);
r.mFgsNotificationWasDeferred = false;
signalForegroundServiceObserversLocked(r);
resetFgsRestrictionLocked(r);
@@ -2165,6 +2226,118 @@
return now < eligible;
}
+ /**
+ * Validate if the given service can start a foreground service with given type.
+ *
+ * @return A pair, where the first parameter is the result code and second is the exception
+ * object if it fails to start a foreground service with given type.
+ */
+ @NonNull
+ private Pair<Integer, RuntimeException> validateForegroundServiceType(ServiceRecord r,
+ @ForegroundServiceType int type,
+ @ForegroundServiceType int defaultToType) {
+ final ForegroundServiceTypePolicy policy = ForegroundServiceTypePolicy.getDefaultPolicy();
+ final ForegroundServiceTypePolicyInfo policyInfo =
+ policy.getForegroundServiceTypePolicyInfo(type, defaultToType);
+ final @ForegroundServicePolicyCheckCode int code = policy.checkForegroundServiceTypePolicy(
+ mAm.mContext, r.packageName, r.app.uid, r.app.getPid(),
+ r.mAllowWhileInUsePermissionInFgs, policyInfo);
+ RuntimeException exception = null;
+ switch (code) {
+ case FGS_TYPE_POLICY_CHECK_DEPRECATED: {
+ final String msg = "Starting FGS with type "
+ + ServiceInfo.foregroundServiceTypeToLabel(type)
+ + " code=" + code
+ + " callerApp=" + r.app
+ + " targetSDK=" + r.app.info.targetSdkVersion;
+ Slog.wtfQuiet(TAG, msg);
+ Slog.w(TAG, msg);
+ } break;
+ case FGS_TYPE_POLICY_CHECK_DISABLED: {
+ exception = new ForegroundServiceTypeNotAllowedException(
+ "Starting FGS with type "
+ + ServiceInfo.foregroundServiceTypeToLabel(type)
+ + " callerApp=" + r.app
+ + " targetSDK=" + r.app.info.targetSdkVersion
+ + " has been prohibited");
+ } break;
+ case FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_PERMISSIVE: {
+ final String msg = "Starting FGS with type "
+ + ServiceInfo.foregroundServiceTypeToLabel(type)
+ + " code=" + code
+ + " callerApp=" + r.app
+ + " targetSDK=" + r.app.info.targetSdkVersion
+ + " requiredPermissions=" + policyInfo.toPermissionString();
+ Slog.wtfQuiet(TAG, msg);
+ Slog.w(TAG, msg);
+ } break;
+ case FGS_TYPE_POLICY_CHECK_PERMISSION_DENIED_ENFORCED: {
+ exception = new SecurityException("Starting FGS with type "
+ + ServiceInfo.foregroundServiceTypeToLabel(type)
+ + " callerApp=" + r.app
+ + " targetSDK=" + r.app.info.targetSdkVersion
+ + " requires permissions: "
+ + policyInfo.toPermissionString());
+ } break;
+ case FGS_TYPE_POLICY_CHECK_OK:
+ default:
+ break;
+ }
+ return Pair.create(code, exception);
+ }
+
+ private class SystemExemptedFgsTypePermission extends ForegroundServiceTypePermission {
+ SystemExemptedFgsTypePermission() {
+ super("System exempted");
+ }
+
+ @Override
+ public int checkPermission(@NonNull Context context, int callerUid, int callerPid,
+ @NonNull String packageName, boolean allowWhileInUse) {
+ final AppRestrictionController appRestrictionController = mAm.mAppRestrictionController;
+ @ReasonCode int reason = appRestrictionController
+ .getPotentialSystemExemptionReason(callerUid);
+ if (reason == REASON_DENIED) {
+ reason = appRestrictionController
+ .getPotentialSystemExemptionReason(callerUid, packageName);
+ if (reason == REASON_DENIED) {
+ reason = appRestrictionController
+ .getPotentialUserAllowedExemptionReason(callerUid, packageName);
+ }
+ }
+ switch (reason) {
+ case REASON_SYSTEM_UID:
+ case REASON_SYSTEM_ALLOW_LISTED:
+ case REASON_DEVICE_DEMO_MODE:
+ case REASON_DISALLOW_APPS_CONTROL:
+ case REASON_DEVICE_OWNER:
+ case REASON_PROFILE_OWNER:
+ case REASON_PROC_STATE_PERSISTENT:
+ case REASON_PROC_STATE_PERSISTENT_UI:
+ case REASON_SYSTEM_MODULE:
+ case REASON_CARRIER_PRIVILEGED_APP:
+ case REASON_DPO_PROTECTED_APP:
+ case REASON_ACTIVE_DEVICE_ADMIN:
+ case REASON_ROLE_EMERGENCY:
+ case REASON_ALLOWLISTED_PACKAGE:
+ return PERMISSION_GRANTED;
+ default:
+ return PERMISSION_DENIED;
+ }
+ }
+ }
+
+ private void initSystemExemptedFgsTypePermission() {
+ final ForegroundServiceTypePolicy policy = ForegroundServiceTypePolicy.getDefaultPolicy();
+ final ForegroundServiceTypePolicyInfo policyInfo =
+ policy.getForegroundServiceTypePolicyInfo(
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED,
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
+ if (policyInfo != null) {
+ policyInfo.setCustomPermission(new SystemExemptedFgsTypePermission());
+ }
+ }
+
ServiceNotificationPolicy applyForegroundServiceNotificationLocked(Notification notification,
final String tag, final int id, final String pkg, final int userId) {
// By nature of the FGS API, all FGS notifications have a null tag
@@ -4777,10 +4950,11 @@
unregisterAppOpCallbackLocked(r);
r.mFgsExitTime = SystemClock.uptimeMillis();
logFGSStateChangeLocked(r,
- FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
+ FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT,
r.mFgsExitTime > r.mFgsEnterTime
? (int) (r.mFgsExitTime - r.mFgsEnterTime) : 0,
- FGS_STOP_REASON_STOP_SERVICE);
+ FGS_STOP_REASON_STOP_SERVICE,
+ FGS_TYPE_POLICY_CHECK_UNKNOWN);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
}
@@ -7020,17 +7194,20 @@
* @param r ServiceRecord
* @param state one of ENTER/EXIT/DENIED event.
* @param durationMs Only meaningful for EXIT event, the duration from ENTER and EXIT state.
+ * @param fgsStopReason why was this FGS stopped.
+ * @param fgsTypeCheckCode The FGS type policy check result.
*/
private void logFGSStateChangeLocked(ServiceRecord r, int state, int durationMs,
- @FgsStopReason int fgsStopReason) {
+ @FgsStopReason int fgsStopReason,
+ @ForegroundServicePolicyCheckCode int fgsTypeCheckCode) {
if (!ActivityManagerUtils.shouldSamplePackageForAtom(
r.packageName, mAm.mConstants.mFgsAtomSampleRate)) {
return;
}
boolean allowWhileInUsePermissionInFgs;
@PowerExemptionManager.ReasonCode int fgsStartReasonCode;
- if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER
- || state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
+ if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER
+ || state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
allowWhileInUsePermissionInFgs = r.mAllowWhileInUsePermissionInFgsAtEntering;
fgsStartReasonCode = r.mAllowStartForegroundAtEntering;
} else {
@@ -7056,14 +7233,15 @@
r.mStartForegroundCount,
ActivityManagerUtils.hashComponentNameForAtom(r.shortInstanceName),
r.mFgsHasNotificationPermission,
- r.foregroundServiceType);
+ r.foregroundServiceType,
+ fgsTypeCheckCode);
int event = 0;
- if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
+ if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER) {
event = EventLogTags.AM_FOREGROUND_SERVICE_START;
- } else if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
+ } else if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT) {
event = EventLogTags.AM_FOREGROUND_SERVICE_STOP;
- } else if (state == FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED) {
+ } else if (state == FOREGROUND_SERVICE_STATE_CHANGED__STATE__DENIED) {
event = EventLogTags.AM_FOREGROUND_SERVICE_DENIED;
} else {
// Unknown event.
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 16fe121..003f7f0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -249,6 +249,18 @@
private static final String KEY_MAX_PHANTOM_PROCESSES = "max_phantom_processes";
/**
+ * Enables proactive killing of cached apps
+ */
+ private static final String KEY_PROACTIVE_KILLS_ENABLED = "proactive_kills_enabled";
+
+ /**
+ * Trim LRU cached app when swap falls below this minimum percentage.
+ *
+ * Depends on KEY_PROACTIVE_KILLS_ENABLED
+ */
+ private static final String KEY_LOW_SWAP_THRESHOLD_PERCENT = "low_swap_threshold_percent";
+
+ /**
* Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
* Settings.Global. This allows it to be set experimentally unless it has been
* enabled/disabled in developer options. Defaults to false.
@@ -874,6 +886,10 @@
*/
private static final long DEFAULT_MIN_ASSOC_LOG_DURATION = 5 * 60 * 1000; // 5 mins
+ private static final boolean DEFAULT_PROACTIVE_KILLS_ENABLED = false;
+
+ private static final float DEFAULT_LOW_SWAP_THRESHOLD_PERCENT = 0.10f;
+
private static final String KEY_MIN_ASSOC_LOG_DURATION = "min_assoc_log_duration";
public static long MIN_ASSOC_LOG_DURATION = DEFAULT_MIN_ASSOC_LOG_DURATION;
@@ -904,6 +920,8 @@
public static boolean BINDER_HEAVY_HITTER_AUTO_SAMPLER_ENABLED;
public static int BINDER_HEAVY_HITTER_AUTO_SAMPLER_BATCHSIZE;
public static float BINDER_HEAVY_HITTER_AUTO_SAMPLER_THRESHOLD;
+ public static boolean PROACTIVE_KILLS_ENABLED = DEFAULT_PROACTIVE_KILLS_ENABLED;
+ public static float LOW_SWAP_THRESHOLD_PERCENT = DEFAULT_LOW_SWAP_THRESHOLD_PERCENT;
private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
new OnPropertiesChangedListener() {
@@ -1040,6 +1058,12 @@
case KEY_MAX_SERVICE_CONNECTIONS_PER_PROCESS:
updateMaxServiceConnectionsPerProcess();
break;
+ case KEY_PROACTIVE_KILLS_ENABLED:
+ updateProactiveKillsEnabled();
+ break;
+ case KEY_LOW_SWAP_THRESHOLD_PERCENT:
+ updateLowSwapThresholdPercent();
+ break;
default:
break;
}
@@ -1660,6 +1684,20 @@
CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3;
}
+ private void updateProactiveKillsEnabled() {
+ PROACTIVE_KILLS_ENABLED = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_PROACTIVE_KILLS_ENABLED,
+ DEFAULT_PROACTIVE_KILLS_ENABLED);
+ }
+
+ private void updateLowSwapThresholdPercent() {
+ LOW_SWAP_THRESHOLD_PERCENT = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_LOW_SWAP_THRESHOLD_PERCENT,
+ DEFAULT_LOW_SWAP_THRESHOLD_PERCENT);
+ }
+
private void updateMinAssocLogDuration() {
MIN_ASSOC_LOG_DURATION = DeviceConfig.getLong(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MIN_ASSOC_LOG_DURATION,
@@ -1860,6 +1898,10 @@
pw.print("="); pw.println(mNetworkAccessTimeoutMs);
pw.print(" "); pw.print(KEY_MAX_SERVICE_CONNECTIONS_PER_PROCESS);
pw.print("="); pw.println(mMaxServiceConnectionsPerProcess);
+ pw.print(" "); pw.print(KEY_PROACTIVE_KILLS_ENABLED);
+ pw.print("="); pw.println(PROACTIVE_KILLS_ENABLED);
+ pw.print(" "); pw.print(KEY_LOW_SWAP_THRESHOLD_PERCENT);
+ pw.print("="); pw.println(LOW_SWAP_THRESHOLD_PERCENT);
pw.println();
if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7d64077..d44b727 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -378,12 +378,10 @@
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintFunction;
-import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.UndecFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.BootReceiver;
@@ -18904,19 +18902,20 @@
}
@Override
- public SyncNotedAppOp startProxyOperation(int code,
+ public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
@AttributionFlags int proxiedAttributionFlags, int attributionChainId,
- @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean,
- Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) {
+ @NonNull UndecFunction<IBinder, Integer, AttributionSource,
+ Boolean, Boolean, String, Boolean, Boolean, Integer, Integer, Integer,
+ SyncNotedAppOp> superImpl) {
if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
final int shellUid = UserHandle.getUid(UserHandle.getUserId(
attributionSource.getUid()), Process.SHELL_UID);
final long identity = Binder.clearCallingIdentity();
try {
- return superImpl.apply(code, new AttributionSource(shellUid,
+ return superImpl.apply(clientId, code, new AttributionSource(shellUid,
"com.android.shell", attributionSource.getAttributionTag(),
attributionSource.getToken(), attributionSource.getNext()),
startIfModeDefault, shouldCollectAsyncNotedOp, message,
@@ -18926,21 +18925,22 @@
Binder.restoreCallingIdentity(identity);
}
}
- return superImpl.apply(code, attributionSource, startIfModeDefault,
+ return superImpl.apply(clientId, code, attributionSource, startIfModeDefault,
shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
@Override
- public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
- boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource,
- Boolean, Void> superImpl) {
+ public void finishProxyOperation(@NonNull IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation,
+ @NonNull QuadFunction<IBinder, Integer, AttributionSource, Boolean,
+ Void> superImpl) {
if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) {
final int shellUid = UserHandle.getUid(UserHandle.getUserId(
attributionSource.getUid()), Process.SHELL_UID);
final long identity = Binder.clearCallingIdentity();
try {
- superImpl.apply(code, new AttributionSource(shellUid,
+ superImpl.apply(clientId, code, new AttributionSource(shellUid,
"com.android.shell", attributionSource.getAttributionTag(),
attributionSource.getToken(), attributionSource.getNext()),
skipProxyOperation);
@@ -18948,7 +18948,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- superImpl.apply(code, attributionSource, skipProxyOperation);
+ superImpl.apply(clientId, code, attributionSource, skipProxyOperation);
}
private boolean isTargetOp(int code) {
diff --git a/services/core/java/com/android/server/am/AppFGSTracker.java b/services/core/java/com/android/server/am/AppFGSTracker.java
index 50515cd..1f98aba 100644
--- a/services/core/java/com/android/server/am/AppFGSTracker.java
+++ b/services/core/java/com/android/server/am/AppFGSTracker.java
@@ -16,10 +16,10 @@
package com.android.server.am;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPES_MAX_INDEX;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
-import static android.content.pm.ServiceInfo.NUM_OF_FOREGROUND_SERVICE_TYPES;
import static android.content.pm.ServiceInfo.foregroundServiceTypeToLabel;
import static android.os.PowerExemptionManager.REASON_DENIED;
@@ -645,7 +645,7 @@
PackageDurations(int uid, String packageName,
MaxTrackingDurationConfig maxTrackingDurationConfig, AppFGSTracker tracker) {
- super(uid, packageName, NUM_OF_FOREGROUND_SERVICE_TYPES + 1, TAG,
+ super(uid, packageName, FOREGROUND_SERVICE_TYPES_MAX_INDEX + 1, TAG,
maxTrackingDurationConfig);
mEvents[DEFAULT_INDEX] = new LinkedList<>();
mTracker = tracker;
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index ba1c3b3..6abf6d8 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -2784,6 +2784,37 @@
*/
@ReasonCode
int getBackgroundRestrictionExemptionReason(int uid) {
+ @ReasonCode int reason = getPotentialSystemExemptionReason(uid);
+ if (reason != REASON_DENIED) {
+ return reason;
+ }
+ final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
+ if (packages != null) {
+ // Check each packages to see if any of them is in the "fixed" exemption cases.
+ for (String pkg : packages) {
+ reason = getPotentialSystemExemptionReason(uid, pkg);
+ if (reason != REASON_DENIED) {
+ return reason;
+ }
+ }
+ // Loop the packages again, and check the user-configurable exemptions.
+ for (String pkg : packages) {
+ reason = getPotentialUserAllowedExemptionReason(uid, pkg);
+ if (reason != REASON_DENIED) {
+ return reason;
+ }
+ }
+ }
+ return REASON_DENIED;
+ }
+
+ /**
+ * @param uid The uid to check.
+ * @return The potential exemption reason of the given uid. The caller must decide
+ * whether or not it should be exempted.
+ */
+ @ReasonCode
+ int getPotentialSystemExemptionReason(int uid) {
if (UserHandle.isCore(uid)) {
return REASON_SYSTEM_UID;
}
@@ -2811,37 +2842,51 @@
} else if (uidProcState <= PROCESS_STATE_PERSISTENT_UI) {
return REASON_PROC_STATE_PERSISTENT_UI;
}
- final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
- if (packages != null) {
- final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
- final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
- final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
- // Check each packages to see if any of them is in the "fixed" exemption cases.
- for (String pkg : packages) {
- if (isSystemModule(pkg)) {
- return REASON_SYSTEM_MODULE;
- } else if (isCarrierApp(pkg)) {
- return REASON_CARRIER_PRIVILEGED_APP;
- } else if (isExemptedFromSysConfig(pkg)) {
- return REASON_SYSTEM_ALLOW_LISTED;
- } else if (mConstantsObserver.mBgRestrictionExemptedPackages.contains(pkg)) {
- return REASON_SYSTEM_ALLOW_LISTED;
- } else if (pm.isPackageStateProtected(pkg, userId)) {
- return REASON_DPO_PROTECTED_APP;
- } else if (appStandbyInternal.isActiveDeviceAdmin(pkg, userId)) {
- return REASON_ACTIVE_DEVICE_ADMIN;
- }
- }
- // Loop the packages again, and check the user-configurable exemptions.
- for (String pkg : packages) {
- if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
- uid, pkg) == AppOpsManager.MODE_ALLOWED) {
- return REASON_OP_ACTIVATE_VPN;
- } else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
- uid, pkg) == AppOpsManager.MODE_ALLOWED) {
- return REASON_OP_ACTIVATE_PLATFORM_VPN;
- }
- }
+ return REASON_DENIED;
+ }
+
+ /**
+ * @param uid The uid to check.
+ * @param pkgName The package name to check.
+ * @return The potential system-fixed exemption reason of the given uid/package. The caller
+ * must decide whether or not it should be exempted.
+ */
+ @ReasonCode
+ int getPotentialSystemExemptionReason(int uid, String pkg) {
+ final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
+ final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
+ final int userId = UserHandle.getUserId(uid);
+ if (isSystemModule(pkg)) {
+ return REASON_SYSTEM_MODULE;
+ } else if (isCarrierApp(pkg)) {
+ return REASON_CARRIER_PRIVILEGED_APP;
+ } else if (isExemptedFromSysConfig(pkg)) {
+ return REASON_SYSTEM_ALLOW_LISTED;
+ } else if (mConstantsObserver.mBgRestrictionExemptedPackages.contains(pkg)) {
+ return REASON_SYSTEM_ALLOW_LISTED;
+ } else if (pm.isPackageStateProtected(pkg, userId)) {
+ return REASON_DPO_PROTECTED_APP;
+ } else if (appStandbyInternal.isActiveDeviceAdmin(pkg, userId)) {
+ return REASON_ACTIVE_DEVICE_ADMIN;
+ }
+ return REASON_DENIED;
+ }
+
+ /**
+ * @param uid The uid to check.
+ * @param pkgName The package name to check.
+ * @return The potential user-allowed exemption reason of the given uid/package. The caller
+ * must decide whether or not it should be exempted.
+ */
+ @ReasonCode
+ int getPotentialUserAllowedExemptionReason(int uid, String pkg) {
+ final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
+ if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
+ uid, pkg) == AppOpsManager.MODE_ALLOWED) {
+ return REASON_OP_ACTIVATE_VPN;
+ } else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
+ uid, pkg) == AppOpsManager.MODE_ALLOWED) {
+ return REASON_OP_ACTIVATE_PLATFORM_VPN;
}
if (isRoleHeldByUid(RoleManager.ROLE_DIALER, uid)) {
return REASON_ROLE_DIALER;
@@ -2852,6 +2897,7 @@
if (isOnDeviceIdleAllowlist(uid)) {
return REASON_ALLOWLISTED_PACKAGE;
}
+ final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
if (am.isAssociatedCompanionApp(UserHandle.getUserId(uid), uid)) {
return REASON_COMPANION_DEVICE_MANAGER;
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index ce78d1b..008d95a 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -239,7 +239,7 @@
}
case MSG_DELIVERY_TIMEOUT_SOFT: {
synchronized (mService) {
- deliveryTimeoutSoftLocked((BroadcastProcessQueue) msg.obj);
+ deliveryTimeoutSoftLocked((BroadcastProcessQueue) msg.obj, msg.arg1);
}
return true;
}
@@ -746,9 +746,10 @@
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
- final long timeout = r.isForeground() ? mFgConstants.TIMEOUT : mBgConstants.TIMEOUT;
- mLocalHandler.sendMessageDelayed(
- Message.obtain(mLocalHandler, MSG_DELIVERY_TIMEOUT_SOFT, queue), timeout);
+ final int softTimeoutMillis = (int) (r.isForeground() ? mFgConstants.TIMEOUT
+ : mBgConstants.TIMEOUT);
+ mLocalHandler.sendMessageDelayed(Message.obtain(mLocalHandler,
+ MSG_DELIVERY_TIMEOUT_SOFT, softTimeoutMillis, 0, queue), softTimeoutMillis);
}
if (r.allowBackgroundActivityStarts) {
@@ -835,15 +836,17 @@
r.resultTo = null;
}
- private void deliveryTimeoutSoftLocked(@NonNull BroadcastProcessQueue queue) {
+ private void deliveryTimeoutSoftLocked(@NonNull BroadcastProcessQueue queue,
+ int softTimeoutMillis) {
if (queue.app != null) {
// Instead of immediately triggering an ANR, extend the timeout by
// the amount of time the process was runnable-but-waiting; we're
// only willing to do this once before triggering an hard ANR
final long cpuDelayTime = queue.app.getCpuDelayTime() - queue.lastCpuDelayTime;
- final long timeout = MathUtils.constrain(cpuDelayTime, 0, mConstants.TIMEOUT);
+ final long hardTimeoutMillis = MathUtils.constrain(cpuDelayTime, 0, softTimeoutMillis);
mLocalHandler.sendMessageDelayed(
- Message.obtain(mLocalHandler, MSG_DELIVERY_TIMEOUT_HARD, queue), timeout);
+ Message.obtain(mLocalHandler, MSG_DELIVERY_TIMEOUT_HARD, queue),
+ hardTimeoutMillis);
} else {
deliveryTimeoutHardLocked(queue);
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 2d7b0dc..e34cd12 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -845,7 +845,7 @@
/**
* Retrieves the free swap percentage.
*/
- static private native double getFreeSwapPercent();
+ static native double getFreeSwapPercent();
/**
* Retrieves the total used physical ZRAM
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 68e5a5d..eb2b7d4 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1118,6 +1118,12 @@
private long mNextNoKillDebugMessageTime;
+ private double mLastFreeSwapPercent = 1.00;
+
+ private static double getFreeSwapPercent() {
+ return CachedAppOptimizer.getFreeSwapPercent();
+ }
+
@GuardedBy({"mService", "mProcLock"})
private boolean updateAndTrimProcessLSP(final long now, final long nowElapsed,
final long oldTime, final ActiveUids activeUids, @OomAdjReason int oomAdjReason) {
@@ -1142,6 +1148,11 @@
int numEmpty = 0;
int numTrimming = 0;
+ boolean proactiveKillsEnabled = mConstants.PROACTIVE_KILLS_ENABLED;
+ double lowSwapThresholdPercent = mConstants.LOW_SWAP_THRESHOLD_PERCENT;
+ double freeSwapPercent = proactiveKillsEnabled ? getFreeSwapPercent() : 1.00;
+ ProcessRecord lruCachedApp = null;
+
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
@@ -1179,6 +1190,8 @@
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
true);
+ } else if (proactiveKillsEnabled) {
+ lruCachedApp = app;
}
break;
case PROCESS_STATE_CACHED_EMPTY:
@@ -1198,6 +1211,8 @@
ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY,
true);
+ } else if (proactiveKillsEnabled) {
+ lruCachedApp = app;
}
}
break;
@@ -1229,6 +1244,20 @@
}
}
+ if (proactiveKillsEnabled // Proactive kills enabled?
+ && doKillExcessiveProcesses // Should kill excessive processes?
+ && freeSwapPercent < lowSwapThresholdPercent // Swap below threshold?
+ && lruCachedApp != null // If no cached app, let LMKD decide
+ // If swap is non-decreasing, give reclaim a chance to catch up
+ && freeSwapPercent < mLastFreeSwapPercent) {
+ lruCachedApp.killLocked("swap low and too many cached",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_TOO_MANY_CACHED,
+ true);
+ }
+
+ mLastFreeSwapPercent = freeSwapPercent;
+
return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
}
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 31d707d..64f2aa3 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -1314,16 +1314,9 @@
void onUserSwitching(TargetUser from, TargetUser to) {
final int toUserId = to.getUserIdentifier();
- if (from != null) {
- synchronized (mLock) {
- final int fromUserId = from.getUserIdentifier();
- if (mSettings.containsKey(fromUserId)) {
- sendUserMessage(fromUserId, REMOVE_SETTINGS, "ON_USER_SWITCHING",
- 0 /*delayMillis*/);
- }
- }
- }
-
+ // we want to re-populate the setting when switching user as the device config may have
+ // changed, which will only update for the previous user, see
+ // DeviceConfigListener#onPropertiesChanged.
sendUserMessage(toUserId, POPULATE_GAME_MODE_SETTINGS, "ON_USER_SWITCHING",
0 /*delayMillis*/);
@@ -1392,8 +1385,9 @@
Slog.v(TAG, "Package configuration not found for " + packageName);
return;
}
+ } else {
+ updateFps(packageConfig, packageName, gameMode, userId);
}
- updateFps(packageConfig, packageName, gameMode, userId);
updateUseAngle(packageName, gameMode);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a58583c..7e00c32 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2920,18 +2920,18 @@
}
@Override
- public SyncNotedAppOp startProxyOperation(int code,
+ public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
@AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
- return mCheckOpsDelegateDispatcher.startProxyOperation(code, attributionSource,
+ return mCheckOpsDelegateDispatcher.startProxyOperation(clientId, code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags,
attributionChainId);
}
- private SyncNotedAppOp startProxyOperationImpl(int code,
+ private SyncNotedAppOp startProxyOperationImpl(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource,
boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message,
boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags
@@ -2940,11 +2940,9 @@
final int proxyUid = attributionSource.getUid();
final String proxyPackageName = attributionSource.getPackageName();
final String proxyAttributionTag = attributionSource.getAttributionTag();
- final IBinder proxyToken = attributionSource.getToken();
final int proxiedUid = attributionSource.getNextUid();
final String proxiedPackageName = attributionSource.getNextPackageName();
final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
- final IBinder proxiedToken = attributionSource.getNextToken();
verifyIncomingProxyUid(attributionSource);
verifyIncomingOp(code);
@@ -2986,7 +2984,7 @@
if (!skipProxyOperation) {
// Test if the proxied operation will succeed before starting the proxy operation
- final SyncNotedAppOp testProxiedOp = startOperationUnchecked(proxiedToken, code,
+ final SyncNotedAppOp testProxiedOp = startOperationUnchecked(clientId, code,
proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault,
shouldCollectAsyncNotedOp, message, shouldCollectMessage,
@@ -2998,7 +2996,7 @@
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
- final SyncNotedAppOp proxyAppOp = startOperationUnchecked(proxyToken, code, proxyUid,
+ final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid,
resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null,
proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message,
shouldCollectMessage, proxyAttributionFlags, attributionChainId,
@@ -3008,7 +3006,7 @@
}
}
- return startOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName,
+ return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag,
proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, proxiedAttributionFlags, attributionChainId,
@@ -3151,22 +3149,20 @@
}
@Override
- public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
- boolean skipProxyOperation) {
- mCheckOpsDelegateDispatcher.finishProxyOperation(code, attributionSource,
+ public void finishProxyOperation(@NonNull IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
+ mCheckOpsDelegateDispatcher.finishProxyOperation(clientId, code, attributionSource,
skipProxyOperation);
}
- private Void finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource,
- boolean skipProxyOperation) {
+ private Void finishProxyOperationImpl(IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
final int proxyUid = attributionSource.getUid();
final String proxyPackageName = attributionSource.getPackageName();
final String proxyAttributionTag = attributionSource.getAttributionTag();
- final IBinder proxyToken = attributionSource.getToken();
final int proxiedUid = attributionSource.getNextUid();
final String proxiedPackageName = attributionSource.getNextPackageName();
final String proxiedAttributionTag = attributionSource.getNextAttributionTag();
- final IBinder proxiedToken = attributionSource.getNextToken();
skipProxyOperation = skipProxyOperation
&& isCallerAndAttributionTrusted(attributionSource);
@@ -3185,7 +3181,7 @@
}
if (!skipProxyOperation) {
- finishOperationUnchecked(proxyToken, code, proxyUid, resolvedProxyPackageName,
+ finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName,
proxyAttributionTag);
}
@@ -3195,7 +3191,7 @@
return null;
}
- finishOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName,
+ finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName,
proxiedAttributionTag);
return null;
@@ -6262,7 +6258,6 @@
Objects.requireNonNull(stackTrace);
Preconditions.checkArgument(op >= 0);
Preconditions.checkArgument(op < AppOpsManager._NUM_OP);
- Objects.requireNonNull(version);
NoteOpTrace noteOpTrace = new NoteOpTrace(stackTrace, op, packageName, version);
@@ -6436,42 +6431,42 @@
attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl);
}
- public SyncNotedAppOp startProxyOperation(int code,
+ public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
@AttributionFlags int proxiedAttributionFlags, int attributionChainId) {
if (mPolicy != null) {
if (mCheckOpsDelegate != null) {
- return mPolicy.startProxyOperation(code, attributionSource,
+ return mPolicy.startProxyOperation(clientId, code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
proxiedAttributionFlags, attributionChainId,
this::startDelegateProxyOperationImpl);
} else {
- return mPolicy.startProxyOperation(code, attributionSource,
+ return mPolicy.startProxyOperation(clientId, code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
proxiedAttributionFlags, attributionChainId,
AppOpsService.this::startProxyOperationImpl);
}
} else if (mCheckOpsDelegate != null) {
- return startDelegateProxyOperationImpl(code, attributionSource,
+ return startDelegateProxyOperationImpl(clientId, code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
proxiedAttributionFlags, attributionChainId);
}
- return startProxyOperationImpl(code, attributionSource, startIfModeDefault,
+ return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault,
shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
- private SyncNotedAppOp startDelegateProxyOperationImpl(int code,
+ private SyncNotedAppOp startDelegateProxyOperationImpl(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
@AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) {
- return mCheckOpsDelegate.startProxyOperation(code, attributionSource,
+ return mCheckOpsDelegate.startProxyOperation(clientId, code, attributionSource,
startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs,
attributionChainId, AppOpsService.this::startProxyOperationImpl);
@@ -6500,27 +6495,28 @@
AppOpsService.this::finishOperationImpl);
}
- public void finishProxyOperation(int code,
+ public void finishProxyOperation(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
if (mPolicy != null) {
if (mCheckOpsDelegate != null) {
- mPolicy.finishProxyOperation(code, attributionSource,
+ mPolicy.finishProxyOperation(clientId, code, attributionSource,
skipProxyOperation, this::finishDelegateProxyOperationImpl);
} else {
- mPolicy.finishProxyOperation(code, attributionSource,
+ mPolicy.finishProxyOperation(clientId, code, attributionSource,
skipProxyOperation, AppOpsService.this::finishProxyOperationImpl);
}
} else if (mCheckOpsDelegate != null) {
- finishDelegateProxyOperationImpl(code, attributionSource, skipProxyOperation);
+ finishDelegateProxyOperationImpl(clientId, code, attributionSource,
+ skipProxyOperation);
} else {
- finishProxyOperationImpl(code, attributionSource, skipProxyOperation);
+ finishProxyOperationImpl(clientId, code, attributionSource, skipProxyOperation);
}
}
- private Void finishDelegateProxyOperationImpl(int code,
+ private Void finishDelegateProxyOperationImpl(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean skipProxyOperation) {
- mCheckOpsDelegate.finishProxyOperation(code, attributionSource, skipProxyOperation,
- AppOpsService.this::finishProxyOperationImpl);
+ mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource,
+ skipProxyOperation, AppOpsService.this::finishProxyOperationImpl);
return null;
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Mutable.java b/services/core/java/com/android/server/broadcastradio/hal2/Mutable.java
index a9d8054..a6cf72c 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Mutable.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Mutable.java
@@ -34,13 +34,4 @@
public Mutable() {
value = null;
}
-
- /**
- * Initialize value with specific value.
- *
- * @param value initial value.
- */
- public Mutable(E value) {
- this.value = value;
- }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Utils.java b/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
index f6e90ef..188c25d 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
@@ -25,7 +25,7 @@
AM_LW,
AM_MW,
AM_SW,
-};
+}
class Utils {
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 573bf19..5646e1b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -20,6 +20,8 @@
import static com.android.server.hdmi.Constants.ADDR_BACKUP_2;
import static com.android.server.hdmi.Constants.ADDR_TV;
+import static java.util.Map.entry;
+
import android.annotation.Nullable;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
@@ -45,7 +47,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -57,38 +58,34 @@
private static final String TAG = "HdmiUtils";
- private static final Map<Integer, List<Integer>> ADDRESS_TO_TYPE =
- new HashMap<Integer, List<Integer>>() {
- {
- put(Constants.ADDR_TV, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV));
- put(Constants.ADDR_RECORDER_1,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER));
- put(Constants.ADDR_RECORDER_2,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER));
- put(Constants.ADDR_TUNER_1, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER));
- put(Constants.ADDR_PLAYBACK_1,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK));
- put(Constants.ADDR_AUDIO_SYSTEM,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM));
- put(Constants.ADDR_TUNER_2, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER));
- put(Constants.ADDR_TUNER_3, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER));
- put(Constants.ADDR_PLAYBACK_2,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK));
- put(Constants.ADDR_RECORDER_3,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER));
- put(Constants.ADDR_TUNER_4, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER));
- put(Constants.ADDR_PLAYBACK_3,
- Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK));
- put(Constants.ADDR_BACKUP_1, Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
- HdmiDeviceInfo.DEVICE_RECORDER, HdmiDeviceInfo.DEVICE_TUNER,
- HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR));
- put(Constants.ADDR_BACKUP_2, Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
- HdmiDeviceInfo.DEVICE_RECORDER, HdmiDeviceInfo.DEVICE_TUNER,
- HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR));
- put(Constants.ADDR_SPECIFIC_USE, Lists.newArrayList(ADDR_TV));
- put(Constants.ADDR_UNREGISTERED, Collections.emptyList());
- }
- };
+ private static final Map<Integer, List<Integer>> ADDRESS_TO_TYPE = Map.ofEntries(
+ entry(Constants.ADDR_TV, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV)),
+ entry(Constants.ADDR_RECORDER_1,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER)),
+ entry(Constants.ADDR_RECORDER_2,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER)),
+ entry(Constants.ADDR_TUNER_1, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER)),
+ entry(Constants.ADDR_PLAYBACK_1,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK)),
+ entry(Constants.ADDR_AUDIO_SYSTEM,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM)),
+ entry(Constants.ADDR_TUNER_2, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER)),
+ entry(Constants.ADDR_TUNER_3, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER)),
+ entry(Constants.ADDR_PLAYBACK_2,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK)),
+ entry(Constants.ADDR_RECORDER_3,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_RECORDER)),
+ entry(Constants.ADDR_TUNER_4, Lists.newArrayList(HdmiDeviceInfo.DEVICE_TUNER)),
+ entry(Constants.ADDR_PLAYBACK_3,
+ Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK)),
+ entry(Constants.ADDR_BACKUP_1, Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
+ HdmiDeviceInfo.DEVICE_RECORDER, HdmiDeviceInfo.DEVICE_TUNER,
+ HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR)),
+ entry(Constants.ADDR_BACKUP_2, Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
+ HdmiDeviceInfo.DEVICE_RECORDER, HdmiDeviceInfo.DEVICE_TUNER,
+ HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR)),
+ entry(Constants.ADDR_SPECIFIC_USE, Lists.newArrayList(ADDR_TV)),
+ entry(Constants.ADDR_UNREGISTERED, Collections.emptyList()));
private static final String[] DEFAULT_NAMES = {
"TV",
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index cb615a9..8497dfb 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1814,8 +1814,8 @@
*/
public boolean transferTouchFocus(@NonNull IBinder fromChannelToken,
@NonNull IBinder toChannelToken) {
- Objects.nonNull(fromChannelToken);
- Objects.nonNull(toChannelToken);
+ Objects.requireNonNull(fromChannelToken);
+ Objects.requireNonNull(toChannelToken);
return mNative.transferTouchFocus(fromChannelToken, toChannelToken,
false /* isDragDrop */);
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
index 4f6d0d4..e46b8c0c 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
@@ -523,9 +523,9 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder(100);
- TransactionRecord[] arr;
+ ContextHubServiceTransaction[] arr;
synchronized (this) {
- arr = mTransactionQueue.toArray(new TransactionRecord[0]);
+ arr = mTransactionQueue.toArray(new ContextHubServiceTransaction[0]);
}
for (int i = 0; i < arr.length; i++) {
sb.append(i + ": " + arr[i] + "\n");
diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index b8abd98..77cd673 100644
--- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
@@ -296,26 +296,24 @@
Log.e(TAG, "Unable to set " + CONFIG_ES_EXTENSION_SEC + ": " + mEsExtensionSec);
}
- Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
- {
- put(CONFIG_SUPL_VER, GnssConfiguration::native_set_supl_version);
- put(CONFIG_SUPL_MODE, GnssConfiguration::native_set_supl_mode);
+ Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>();
- if (isConfigSuplEsSupported(gnssConfigurationIfaceVersion)) {
- put(CONFIG_SUPL_ES, GnssConfiguration::native_set_supl_es);
- }
+ map.put(CONFIG_SUPL_VER, GnssConfiguration::native_set_supl_version);
+ map.put(CONFIG_SUPL_MODE, GnssConfiguration::native_set_supl_mode);
- put(CONFIG_LPP_PROFILE, GnssConfiguration::native_set_lpp_profile);
- put(CONFIG_A_GLONASS_POS_PROTOCOL_SELECT,
- GnssConfiguration::native_set_gnss_pos_protocol_select);
- put(CONFIG_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL,
- GnssConfiguration::native_set_emergency_supl_pdn);
+ if (isConfigSuplEsSupported(gnssConfigurationIfaceVersion)) {
+ map.put(CONFIG_SUPL_ES, GnssConfiguration::native_set_supl_es);
+ }
- if (isConfigGpsLockSupported(gnssConfigurationIfaceVersion)) {
- put(CONFIG_GPS_LOCK, GnssConfiguration::native_set_gps_lock);
- }
- }
- };
+ map.put(CONFIG_LPP_PROFILE, GnssConfiguration::native_set_lpp_profile);
+ map.put(CONFIG_A_GLONASS_POS_PROTOCOL_SELECT,
+ GnssConfiguration::native_set_gnss_pos_protocol_select);
+ map.put(CONFIG_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL,
+ GnssConfiguration::native_set_emergency_supl_pdn);
+
+ if (isConfigGpsLockSupported(gnssConfigurationIfaceVersion)) {
+ map.put(CONFIG_GPS_LOCK, GnssConfiguration::native_set_gps_lock);
+ }
for (Entry<String, SetCarrierProperty> entry : map.entrySet()) {
String propertyName = entry.getKey();
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index bbbf452..1bbcc83 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -852,7 +852,9 @@
Objects.requireNonNull(pkg);
Objects.requireNonNull(group);
Objects.requireNonNull(group.getId());
- Objects.requireNonNull(!TextUtils.isEmpty(group.getName()));
+ if (TextUtils.isEmpty(group.getName())) {
+ throw new IllegalArgumentException("group.getName() can't be empty");
+ }
boolean needsDndChange = false;
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
diff --git a/services/core/java/com/android/server/pm/PerPackageReadTimeouts.java b/services/core/java/com/android/server/pm/PerPackageReadTimeouts.java
index 3b306a8..b310c62a 100644
--- a/services/core/java/com/android/server/pm/PerPackageReadTimeouts.java
+++ b/services/core/java/com/android/server/pm/PerPackageReadTimeouts.java
@@ -16,7 +16,7 @@
package com.android.server.pm;
-import android.annotation.NonNull;;
+import android.annotation.NonNull;
import android.text.TextUtils;
import com.android.internal.util.HexDump;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ac487fa..4a4a231 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -265,7 +265,7 @@
@VisibleForTesting
static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
- private static final int USER_VERSION = 10;
+ private static final int USER_VERSION = 11;
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
@@ -3355,6 +3355,7 @@
final int oldFlags = systemUserData.info.flags;
final int newFlags;
final String newUserType;
+ // TODO(b/256624031): Also handle FLAG_MAIN
if (newHeadlessSystemUserMode) {
newUserType = UserManager.USER_TYPE_SYSTEM_HEADLESS;
newFlags = oldFlags & ~UserInfo.FLAG_FULL;
@@ -3647,6 +3648,22 @@
userVersion = 10;
}
+ if (userVersion < 11) {
+ // Add FLAG_MAIN
+ if (isHeadlessSystemUserMode()) {
+ final UserInfo earliestCreatedUser = getEarliestCreatedFullUser();
+ earliestCreatedUser.flags |= UserInfo.FLAG_MAIN;
+ userIdsToWrite.add(earliestCreatedUser.id);
+ } else {
+ synchronized (mUsersLock) {
+ final UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
+ userData.info.flags |= UserInfo.FLAG_MAIN;
+ userIdsToWrite.add(userData.info.id);
+ }
+ }
+ userVersion = 11;
+ }
+
// Reminder: If you add another upgrade, make sure to increment USER_VERSION too.
// Done with userVersion changes, moving on to deal with userTypeVersion upgrades
@@ -3776,6 +3793,21 @@
userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
}
+ private UserInfo getEarliestCreatedFullUser() {
+ final List<UserInfo> users = getUsersInternal(true, true, true);
+ UserInfo earliestUser = users.get(0);
+ long earliestCreationTime = earliestUser.creationTime;
+ for (int i = 0; i < users.size(); i++) {
+ final UserInfo info = users.get(i);
+ if (info.isFull() && info.isAdmin() && info.creationTime > 0
+ && info.creationTime < earliestCreationTime) {
+ earliestCreationTime = info.creationTime;
+ earliestUser = info;
+ }
+ }
+ return earliestUser;
+ }
+
@GuardedBy({"mPackagesLock"})
private void fallbackToSingleUserLP() {
int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 871420a9..8fb5773 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -262,7 +262,8 @@
private static UserTypeDetails.Builder getDefaultTypeFullSystem() {
return new UserTypeDetails.Builder()
.setName(USER_TYPE_FULL_SYSTEM)
- .setBaseType(FLAG_SYSTEM | FLAG_FULL);
+ .setBaseType(FLAG_SYSTEM | FLAG_FULL)
+ .setDefaultUserInfoPropertyFlags(UserInfo.FLAG_MAIN);
}
/**
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index 5ba209d..9bca155 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -295,6 +295,7 @@
* NOTE: Keep this in sync with the dexopt expectations! Right now that is either "PCL[path]"
* for a PathClassLoader or "DLC[path]" for a DelegateLastClassLoader.
*/
+ @SuppressWarnings("ReturnValueIgnored")
/*package*/ static String encodeClassLoader(String classpath, String classLoaderName) {
classpath.getClass(); // Throw NPE if classpath is null
String classLoaderDexoptEncoding = classLoaderName;
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 28f86ed..83e17a5 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -86,6 +86,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
@@ -165,6 +166,11 @@
COARSE_BACKGROUND_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
+ private static final Set<String> FINE_LOCATION_PERMISSIONS = new ArraySet<>();
+ static {
+ FINE_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
+ }
+
private static final Set<String> ACTIVITY_RECOGNITION_PERMISSIONS = new ArraySet<>();
static {
ACTIVITY_RECOGNITION_PERMISSIONS.add(Manifest.permission.ACTIVITY_RECOGNITION);
@@ -787,6 +793,8 @@
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, COARSE_BACKGROUND_LOCATION_PERMISSIONS,
NEARBY_DEVICES_PERMISSIONS, NOTIFICATION_PERMISSIONS);
+ revokeRuntimePermissions(pm, voiceInteractPackageName, FINE_LOCATION_PERMISSIONS,
+ false, userId);
}
}
@@ -1932,7 +1940,7 @@
mPkgRequestingPerm, newRestrictionExcemptFlags, -1, mUser);
}
- if (newGranted != null && newGranted != mOriginalGranted) {
+ if (newGranted != null && !Objects.equals(newGranted, mOriginalGranted)) {
if (newGranted) {
NO_PM_CACHE.grantPermission(mPermission, mPkgRequestingPerm, mUser);
} else {
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 5a638bb..9ec63fc 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1101,7 +1101,7 @@
if (resolvedPackageName == null) {
return;
}
- appOpsManager.finishOp(accessorSource.getToken(), op,
+ appOpsManager.finishOp(attributionSourceState.token, op,
accessorSource.getUid(), resolvedPackageName,
accessorSource.getAttributionTag());
} else {
@@ -1110,8 +1110,9 @@
if (resolvedAttributionSource.getPackageName() == null) {
return;
}
- appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op),
- resolvedAttributionSource, skipCurrentFinish);
+ appOpsManager.finishProxyOp(attributionSourceState.token,
+ AppOpsManager.opToPublicName(op), resolvedAttributionSource,
+ skipCurrentFinish);
}
RegisteredAttribution registered =
sRunningAttributionSources.remove(current.getToken());
@@ -1227,10 +1228,11 @@
&& next.getNext() == null);
final boolean selfAccess = singleReceiverFromDatasource || next == null;
- final int opMode = performOpTransaction(context, op, current, message,
- forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks,
- selfAccess, singleReceiverFromDatasource, AppOpsManager.OP_NONE,
- AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ final int opMode = performOpTransaction(context, attributionSource.getToken(), op,
+ current, message, forDataDelivery, /*startDataDelivery*/ false,
+ skipCurrentChecks, selfAccess, singleReceiverFromDatasource,
+ AppOpsManager.OP_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE,
+ AppOpsManager.ATTRIBUTION_FLAGS_NONE,
AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE);
switch (opMode) {
@@ -1333,10 +1335,10 @@
attributionSource, next, fromDatasource, startDataDelivery, selfAccess,
isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
- final int opMode = performOpTransaction(context, op, current, message,
- forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
- singleReceiverFromDatasource, attributedOp, proxyAttributionFlags,
- proxiedAttributionFlags, attributionChainId);
+ final int opMode = performOpTransaction(context, attributionSource.getToken(), op,
+ current, message, forDataDelivery, startDataDelivery, skipCurrentChecks,
+ selfAccess, singleReceiverFromDatasource, attributedOp,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
switch (opMode) {
case AppOpsManager.MODE_ERRORED: {
@@ -1481,8 +1483,8 @@
attributionSource, next, /*fromDatasource*/ false, startDataDelivery,
selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE;
- final int opMode = performOpTransaction(context, op, current, message,
- forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
+ final int opMode = performOpTransaction(context, current.getToken(), op, current,
+ message, forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess,
/*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags,
proxiedAttributionFlags, attributionChainId);
@@ -1504,7 +1506,8 @@
}
@SuppressWarnings("ConstantConditions")
- private static int performOpTransaction(@NonNull Context context, int op,
+ private static int performOpTransaction(@NonNull Context context,
+ @NonNull IBinder chainStartToken, int op,
@NonNull AttributionSource attributionSource, @Nullable String message,
boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation,
boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp,
@@ -1566,7 +1569,7 @@
if (selfAccess) {
try {
startedOpResult = appOpsManager.startOpNoThrow(
- resolvedAttributionSource.getToken(), startedOp,
+ chainStartToken, startedOp,
resolvedAttributionSource.getUid(),
resolvedAttributionSource.getPackageName(),
/*startIfModeDefault*/ false,
@@ -1577,14 +1580,14 @@
+ " platform defined runtime permission "
+ AppOpsManager.opToPermission(op) + " while not having "
+ Manifest.permission.UPDATE_APP_OPS_STATS);
- startedOpResult = appOpsManager.startProxyOpNoThrow(attributedOp,
- attributionSource, message, skipProxyOperation,
+ startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken,
+ attributedOp, attributionSource, message, skipProxyOperation,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
} else {
try {
- startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp,
- resolvedAttributionSource, message, skipProxyOperation,
+ startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken,
+ startedOp, resolvedAttributionSource, message, skipProxyOperation,
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
} catch (SecurityException e) {
//TODO 195339480: remove
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index a6d148c..383249f 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -45,13 +45,11 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.function.DecFunction;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
import com.android.internal.util.function.QuintFunction;
-import com.android.internal.util.function.TriFunction;
import com.android.internal.util.function.UndecFunction;
import com.android.server.LocalServices;
@@ -257,14 +255,14 @@
}
@Override
- public SyncNotedAppOp startProxyOperation(int code,
+ public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code,
@NonNull AttributionSource attributionSource, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage,
boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags,
@AttributionFlags int proxiedAttributionFlags, int attributionChainId,
- @NonNull DecFunction<Integer, AttributionSource, Boolean, Boolean, String, Boolean,
- Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) {
- return superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(),
+ @NonNull UndecFunction<IBinder, Integer, AttributionSource, Boolean, Boolean, String,
+ Boolean, Boolean, Integer, Integer, Integer, SyncNotedAppOp> superImpl) {
+ return superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(),
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message,
shouldCollectMessage, skipProxyOperation, proxyAttributionFlags,
@@ -280,10 +278,10 @@
}
@Override
- public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource,
- boolean skipProxyOperation, @NonNull TriFunction<Integer, AttributionSource,
- Boolean, Void> superImpl) {
- superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(),
+ public void finishProxyOperation(@NonNull IBinder clientId, int code,
+ @NonNull AttributionSource attributionSource, boolean skipProxyOperation,
+ @NonNull QuadFunction<IBinder, Integer, AttributionSource, Boolean, Void> superImpl) {
+ superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(),
attributionSource.getPackageName(), attributionSource.getAttributionTag()),
attributionSource, skipProxyOperation);
}
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index dbddb41..2c8fd96 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -1066,7 +1066,28 @@
} finally {
Binder.restoreCallingIdentity(identity);
}
+ }
+ @Override
+ public void notifyRecordingStopped(IBinder sessionToken, String recordingId, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "notifyRecordingStopped");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).notifyRecordingStopped(recordingId);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyRecordingStopped", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b8cd8d9..c875f4a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1897,12 +1897,9 @@
}
}
- private static final HashMap<Integer, String> sWallpaperType = new HashMap<Integer, String>() {
- {
- put(FLAG_SYSTEM, RECORD_FILE);
- put(FLAG_LOCK, RECORD_LOCK_FILE);
- }
- };
+ private static final Map<Integer, String> sWallpaperType = Map.of(
+ FLAG_SYSTEM, RECORD_FILE,
+ FLAG_LOCK, RECORD_LOCK_FILE);
private void errorCheck(int userID) {
sWallpaperType.forEach((type, filename) -> {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index e0644b6..b735b30 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -442,11 +442,12 @@
mRemoveContentMode = other.mRemoveContentMode;
changed = true;
}
- if (other.mShouldShowWithInsecureKeyguard != mShouldShowWithInsecureKeyguard) {
+ if (!Objects.equals(
+ other.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) {
mShouldShowWithInsecureKeyguard = other.mShouldShowWithInsecureKeyguard;
changed = true;
}
- if (other.mShouldShowSystemDecors != mShouldShowSystemDecors) {
+ if (!Objects.equals(other.mShouldShowSystemDecors, mShouldShowSystemDecors)) {
mShouldShowSystemDecors = other.mShouldShowSystemDecors;
changed = true;
}
@@ -458,15 +459,15 @@
mFixedToUserRotation = other.mFixedToUserRotation;
changed = true;
}
- if (other.mIgnoreOrientationRequest != mIgnoreOrientationRequest) {
+ if (!Objects.equals(other.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) {
mIgnoreOrientationRequest = other.mIgnoreOrientationRequest;
changed = true;
}
- if (other.mIgnoreDisplayCutout != mIgnoreDisplayCutout) {
+ if (!Objects.equals(other.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) {
mIgnoreDisplayCutout = other.mIgnoreDisplayCutout;
changed = true;
}
- if (other.mDontMoveToTop != mDontMoveToTop) {
+ if (!Objects.equals(other.mDontMoveToTop, mDontMoveToTop)) {
mDontMoveToTop = other.mDontMoveToTop;
changed = true;
}
@@ -522,14 +523,13 @@
mRemoveContentMode = delta.mRemoveContentMode;
changed = true;
}
- if (delta.mShouldShowWithInsecureKeyguard != null
- && delta.mShouldShowWithInsecureKeyguard
- != mShouldShowWithInsecureKeyguard) {
+ if (delta.mShouldShowWithInsecureKeyguard != null && !Objects.equals(
+ delta.mShouldShowWithInsecureKeyguard, mShouldShowWithInsecureKeyguard)) {
mShouldShowWithInsecureKeyguard = delta.mShouldShowWithInsecureKeyguard;
changed = true;
}
- if (delta.mShouldShowSystemDecors != null
- && delta.mShouldShowSystemDecors != mShouldShowSystemDecors) {
+ if (delta.mShouldShowSystemDecors != null && !Objects.equals(
+ delta.mShouldShowSystemDecors, mShouldShowSystemDecors)) {
mShouldShowSystemDecors = delta.mShouldShowSystemDecors;
changed = true;
}
@@ -543,18 +543,18 @@
mFixedToUserRotation = delta.mFixedToUserRotation;
changed = true;
}
- if (delta.mIgnoreOrientationRequest != null
- && delta.mIgnoreOrientationRequest != mIgnoreOrientationRequest) {
+ if (delta.mIgnoreOrientationRequest != null && !Objects.equals(
+ delta.mIgnoreOrientationRequest, mIgnoreOrientationRequest)) {
mIgnoreOrientationRequest = delta.mIgnoreOrientationRequest;
changed = true;
}
- if (delta.mIgnoreDisplayCutout != null
- && delta.mIgnoreDisplayCutout != mIgnoreDisplayCutout) {
+ if (delta.mIgnoreDisplayCutout != null && !Objects.equals(
+ delta.mIgnoreDisplayCutout, mIgnoreDisplayCutout)) {
mIgnoreDisplayCutout = delta.mIgnoreDisplayCutout;
changed = true;
}
- if (delta.mDontMoveToTop != null
- && delta.mDontMoveToTop != mDontMoveToTop) {
+ if (delta.mDontMoveToTop != null && !Objects.equals(
+ delta.mDontMoveToTop, mDontMoveToTop)) {
mDontMoveToTop = delta.mDontMoveToTop;
changed = true;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3419207..df343db 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -426,7 +426,7 @@
* @see #ENABLE_SHELL_TRANSITIONS
*/
public static final boolean sEnableShellTransitions =
- SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
+ SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, false);
/**
* Allows a fullscreen windowing mode activity to launch in its desired orientation directly
diff --git a/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java b/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java
index 6f2930c..1b70d1d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java
+++ b/services/core/java/com/android/server/wm/WindowManagerThreadPriorityBooster.java
@@ -21,7 +21,7 @@
import static android.os.Process.myTid;
import static android.os.Process.setThreadPriority;
-import static com.android.server.LockGuard.INDEX_WINDOW;;
+import static com.android.server.LockGuard.INDEX_WINDOW;
import com.android.internal.annotations.GuardedBy;
import com.android.server.AnimationThread;
diff --git a/services/java/com/android/server/BootUserInitializer.java b/services/java/com/android/server/BootUserInitializer.java
index 46e59a9..c3329795 100644
--- a/services/java/com/android/server/BootUserInitializer.java
+++ b/services/java/com/android/server/BootUserInitializer.java
@@ -83,9 +83,10 @@
Slogf.d(TAG, "Creating initial user");
t.traceBegin("create-initial-user");
try {
+ int flags = UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN;
// TODO(b/204091126): proper name for user
UserInfo newUser = um.createUserEvenWhenDisallowed("Real User",
- UserManager.USER_TYPE_FULL_SECONDARY, UserInfo.FLAG_ADMIN,
+ UserManager.USER_TYPE_FULL_SECONDARY, flags,
/* disallowedPackages= */ null, /* token= */ null);
Slogf.i(TAG, "Created initial user: %s", newUser.toFullString());
initialUserId = newUser.id;
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index eab3b77..292320e 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -53,6 +53,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -372,7 +373,8 @@
@Override
public boolean equals(Object o) {
ListenerKey key = (ListenerKey) o;
- return key.getPackageName().equals(mPackageName) && key.getUserId() == mUserId
+ return key.getPackageName().equals(mPackageName)
+ && Objects.equals(key.getUserId(), mUserId)
&& key.getShortcutId().equals(mShortcutId);
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 73b1907c..681bfcf 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -56,6 +56,7 @@
"service-jobscheduler",
"service-permission.impl",
"service-sdksandbox.impl",
+ "services.backup",
"services.companion",
"services.core",
"services.devicepolicy",
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index d78f6d83..24e5175 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -1507,6 +1507,39 @@
}
@Test
+ public void testSwitchUser() {
+ mockManageUsersGranted();
+ mockModifyGameModeGranted();
+
+ mockDeviceConfigBattery();
+ final Context context = InstrumentationRegistry.getContext();
+ GameManagerService gameManagerService = new GameManagerService(mMockContext,
+ mTestLooper.getLooper(), context.getFilesDir());
+ startUser(gameManagerService, USER_ID_1);
+ startUser(gameManagerService, USER_ID_2);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+ checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+ GameManager.GAME_MODE_BATTERY);
+ assertEquals(gameManagerService.getGameMode(mPackageName, USER_ID_1),
+ GameManager.GAME_MODE_BATTERY);
+
+ mockDeviceConfigAll();
+ switchUser(gameManagerService, USER_ID_1, USER_ID_2);
+ assertEquals(gameManagerService.getGameMode(mPackageName, USER_ID_2),
+ GameManager.GAME_MODE_STANDARD);
+ checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+ GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_PERFORMANCE);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_2);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+
+ switchUser(gameManagerService, USER_ID_2, USER_ID_1);
+ checkReportedModes(gameManagerService, GameManager.GAME_MODE_STANDARD,
+ GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_PERFORMANCE);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_2);
+ gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
+ }
+
+ @Test
public void testUpdateResolutionScalingFactor() {
mockModifyGameModeGranted();
mockDeviceConfigBattery();
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/BackupAndRestoreFeatureFlagsTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/BackupAndRestoreFeatureFlagsTest.java
new file mode 100644
index 0000000..f535997
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/BackupAndRestoreFeatureFlagsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup;
+
+import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.modules.utils.testing.TestableDeviceConfig;
+
+import static com.google.common.truth.Truth.assertThat;
+
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupAndRestoreFeatureFlagsTest {
+ @Rule
+ public TestableDeviceConfig.TestableDeviceConfigRule
+ mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+
+ @Test
+ public void getBackupTransportFutureTimeoutMillis_notSet_returnsDefault() {
+ assertThat(
+ BackupAndRestoreFeatureFlags.getBackupTransportFutureTimeoutMillis()).isEqualTo(
+ 600000);
+ }
+
+ @Test
+ public void getBackupTransportFutureTimeoutMillis_set_returnsSetValue() {
+ DeviceConfig.setProperty("backup_and_restore", "backup_transport_future_timeout_millis",
+ "1234", false);
+
+ assertThat(
+ BackupAndRestoreFeatureFlags.getBackupTransportFutureTimeoutMillis()).isEqualTo(
+ 1234);
+ }
+
+ @Test
+ public void getBackupTransportCallbackTimeoutMillis_notSet_returnsDefault() {
+ assertThat(
+ BackupAndRestoreFeatureFlags.getBackupTransportCallbackTimeoutMillis()).isEqualTo(
+ 300000);
+ }
+
+ @Test
+ public void getBackupTransportCallbackTimeoutMillis_set_returnsSetValue() {
+ DeviceConfig.setProperty("backup_and_restore", "backup_transport_callback_timeout_millis",
+ "5678", false);
+
+ assertThat(
+ BackupAndRestoreFeatureFlags.getBackupTransportCallbackTimeoutMillis()).isEqualTo(
+ 5678);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java b/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java
index ea746d1..faad961 100644
--- a/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java
+++ b/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java
@@ -30,7 +30,7 @@
import android.view.Display;
import android.view.Surface;
-import java.util.HashMap;
+import java.util.Map;
@RunWith(JUnit4.class)
public class CameraServiceProxyTest {
@@ -75,24 +75,22 @@
/*ignoreResizableAndSdkCheck*/true)).isEqualTo(
CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
// Check rotation and lens facing combinations
- HashMap<Integer, Integer> backFacingMap = new HashMap<Integer, Integer>() {{
- put(Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
- put(Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_90);
- put(Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_270);
- put(Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
- }};
+ Map<Integer, Integer> backFacingMap = Map.of(
+ Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE,
+ Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_90,
+ Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_270,
+ Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
taskInfo.isFixedOrientationPortrait = true;
backFacingMap.forEach((key, value) -> {
assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
key, CameraCharacteristics.LENS_FACING_BACK,
/*ignoreResizableAndSdkCheck*/true)).isEqualTo(value);
});
- HashMap<Integer, Integer> frontFacingMap = new HashMap<Integer, Integer>() {{
- put(Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
- put(Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_270);
- put(Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_90);
- put(Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
- }};
+ Map<Integer, Integer> frontFacingMap = Map.of(
+ Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE,
+ Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_270,
+ Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_90,
+ Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
frontFacingMap.forEach((key, value) -> {
assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
key, CameraCharacteristics.LENS_FACING_FRONT,
diff --git a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
index df672c9..2c4fe53 100644
--- a/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AmbientBrightnessStatsTrackerTest.java
@@ -424,7 +424,7 @@
@Override
public LocalDate getLocalDate() {
- return LocalDate.from(mLocalDate);
+ return mLocalDate;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
index 9092ec3..0884b78 100644
--- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -367,6 +367,7 @@
assertFalse(item_en_us_allcaps.mIsSystemLocale);
}
+ @SuppressWarnings("SelfComparison")
@Test
public void testImeSubtypeListComparator() throws Exception {
final ComponentName imeX1 = new ComponentName("com.example.imeX", "Ime1");
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTestable.java
index 1e855a9..1eb4fa5 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/PasswordSlotManagerTestable.java
@@ -58,4 +58,4 @@
} catch (Exception e) {
}
}
-};
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 0f93598..b64b281 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2727,7 +2727,7 @@
@Test
public void testCreateChannel_addToGroup() {
- NotificationChannelGroup group = new NotificationChannelGroup("group", "");
+ NotificationChannelGroup group = new NotificationChannelGroup("group", "group");
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false));
@@ -3177,8 +3177,8 @@
@Test
public void testGetNotificationChannelGroupWithChannels() throws Exception {
- NotificationChannelGroup group = new NotificationChannelGroup("group", "");
- NotificationChannelGroup other = new NotificationChannelGroup("something else", "");
+ NotificationChannelGroup group = new NotificationChannelGroup("group", "group");
+ NotificationChannelGroup other = new NotificationChannelGroup("something else", "name");
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, other, true);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java
index df63795..7a41b50 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCInputTerminal.java
@@ -46,4 +46,4 @@
// TODO Add reporting specific to this descriptor
super.report(canvas);
}
-};
+}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java
index 4aa8ca2..32275a6 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCOutputTerminal.java
@@ -46,4 +46,4 @@
super.report(canvas);
// TODO Add reporting specific to this descriptor
}
-};
+}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java
index 5ce842e..0692066 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCProcessingUnit.java
@@ -47,4 +47,4 @@
super.report(canvas);
// TODO Add reporting specific to this descriptor
}
-};
+}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java b/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java
index 8e9b0d8..604dd66 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbVCSelectorUnit.java
@@ -47,4 +47,4 @@
super.report(canvas);
// TODO Add reporting specific to this descriptor
}
-};
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 0721c28..3e49aed 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -1321,4 +1321,4 @@
private static final String OP_MESSAGE =
"Providing hotword detection result to VoiceInteractionService";
-};
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index f8bc499..763024f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -913,4 +913,4 @@
}
}
};
-};
+}
diff --git a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
index 8b01cb3..2787d83 100644
--- a/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
+++ b/telephony/common/com/google/android/mms/pdu/EncodedStringValue.java
@@ -199,7 +199,6 @@
*/
@Override
public Object clone() throws CloneNotSupportedException {
- super.clone();
int len = mData.length;
byte[] dstBytes = new byte[len];
System.arraycopy(mData, 0, dstBytes, 0, len);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 936fad5..f38b902 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -8698,6 +8698,15 @@
public static final String KEY_VONR_ENABLED_BOOL = "vonr_enabled_bool";
/**
+ * Boolean indicating the default VoNR user preference setting.
+ * If true, the VoNR setting will be enabled. If false, it will be disabled initially.
+ *
+ * Enabled by default.
+ *
+ */
+ public static final String KEY_VONR_ON_BY_DEFAULT_BOOL = "vonr_on_by_default_bool";
+
+ /**
* Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes
*
* @hide
@@ -9520,6 +9529,7 @@
sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
+ sDefaults.putBoolean(KEY_VONR_ON_BY_DEFAULT_BOOL, true);
sDefaults.putIntArray(KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY, new int[] {});
sDefaults.putLong(KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG,
TimeUnit.MINUTES.toMillis(30));
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 23835a7..b83b400 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1620,29 +1620,26 @@
// If we are not able to find the configuration from carrier config, use the default
// ones.
if (permanentFailureSet == null) {
- permanentFailureSet = new HashSet<Integer>() {
- {
- add(OPERATOR_BARRED);
- add(MISSING_UNKNOWN_APN);
- add(UNKNOWN_PDP_ADDRESS_TYPE);
- add(USER_AUTHENTICATION);
- add(ACTIVATION_REJECT_GGSN);
- add(SERVICE_OPTION_NOT_SUPPORTED);
- add(SERVICE_OPTION_NOT_SUBSCRIBED);
- add(NSAPI_IN_USE);
- add(ONLY_IPV4_ALLOWED);
- add(ONLY_IPV6_ALLOWED);
- add(PROTOCOL_ERRORS);
- add(RADIO_POWER_OFF);
- add(TETHERED_CALL_ACTIVE);
- add(RADIO_NOT_AVAILABLE);
- add(UNACCEPTABLE_NETWORK_PARAMETER);
- add(SIGNAL_LOST);
- add(DUPLICATE_CID);
- add(MATCH_ALL_RULE_NOT_ALLOWED);
- add(ALL_MATCHING_RULES_FAILED);
- }
- };
+ permanentFailureSet = new HashSet<Integer>();
+ permanentFailureSet.add(OPERATOR_BARRED);
+ permanentFailureSet.add(MISSING_UNKNOWN_APN);
+ permanentFailureSet.add(UNKNOWN_PDP_ADDRESS_TYPE);
+ permanentFailureSet.add(USER_AUTHENTICATION);
+ permanentFailureSet.add(ACTIVATION_REJECT_GGSN);
+ permanentFailureSet.add(SERVICE_OPTION_NOT_SUPPORTED);
+ permanentFailureSet.add(SERVICE_OPTION_NOT_SUBSCRIBED);
+ permanentFailureSet.add(NSAPI_IN_USE);
+ permanentFailureSet.add(ONLY_IPV4_ALLOWED);
+ permanentFailureSet.add(ONLY_IPV6_ALLOWED);
+ permanentFailureSet.add(PROTOCOL_ERRORS);
+ permanentFailureSet.add(RADIO_POWER_OFF);
+ permanentFailureSet.add(TETHERED_CALL_ACTIVE);
+ permanentFailureSet.add(RADIO_NOT_AVAILABLE);
+ permanentFailureSet.add(UNACCEPTABLE_NETWORK_PARAMETER);
+ permanentFailureSet.add(SIGNAL_LOST);
+ permanentFailureSet.add(DUPLICATE_CID);
+ permanentFailureSet.add(MATCH_ALL_RULE_NOT_ALLOWED);
+ permanentFailureSet.add(ALL_MATCHING_RULES_FAILED);
}
permanentFailureSet.add(NO_RETRY_FAILURE);
diff --git a/telephony/java/android/telephony/data/QosBearerFilter.java b/telephony/java/android/telephony/data/QosBearerFilter.java
index 0ab7b61..a0d9c1bd 100644
--- a/telephony/java/android/telephony/data/QosBearerFilter.java
+++ b/telephony/java/android/telephony/data/QosBearerFilter.java
@@ -130,6 +130,10 @@
return precedence;
}
+ public int getProtocol() {
+ return protocol;
+ }
+
public static class PortRange implements Parcelable {
int start;
int end;
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index a3cbb4a..33c86d8 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -50,7 +50,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.CancellationException;
@@ -179,10 +178,9 @@
* Used for logging purposes, see {@link #getCapabilitiesString(long)}
* @hide
*/
- private static final Map<Long, String> CAPABILITIES_LOG_MAP = new HashMap<Long, String>() {{
- put(CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL");
- put(CAPABILITY_SIP_DELEGATE_CREATION, "SIP_DELEGATE_CREATION");
- }};
+ private static final Map<Long, String> CAPABILITIES_LOG_MAP = Map.of(
+ CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL",
+ CAPABILITY_SIP_DELEGATE_CREATION, "SIP_DELEGATE_CREATION");
/**
* The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index 090d413..9996b86 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -78,24 +78,22 @@
/**@hide*/
// Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN
// and WWAN are more accurate constants.
- Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP =
- new HashMap<Integer, Integer>() {{
- // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
- // case, since it is defined.
- put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE,
- AccessNetworkConstants.TRANSPORT_TYPE_INVALID);
- put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- put(ImsRegistrationImplBase.REGISTRATION_TECH_NR,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
- AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- /* As the cross sim will be using ePDG tunnel over internet, it behaves
- like IWLAN in most cases. Hence setting the access type as IWLAN
- */
- put(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM,
- AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- }};
+ Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP = Map.of(
+ // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
+ // case, since it is defined.
+ ImsRegistrationImplBase.REGISTRATION_TECH_NONE,
+ AccessNetworkConstants.TRANSPORT_TYPE_INVALID,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ ImsRegistrationImplBase.REGISTRATION_TECH_NR,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+ /* As the cross sim will be using ePDG tunnel over internet, it behaves
+ like IWLAN in most cases. Hence setting the access type as IWLAN
+ */
+ ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
/** @hide */
@NonNull
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index a42327b..174675f 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -34,7 +34,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
import java.util.Map;
/**
@@ -85,11 +84,10 @@
* Used for logging purposes.
* @hide
*/
- public static final Map<Integer, String> FEATURE_LOG_MAP = new HashMap<Integer, String>() {{
- put(FEATURE_EMERGENCY_MMTEL, "EMERGENCY_MMTEL");
- put(FEATURE_MMTEL, "MMTEL");
- put(FEATURE_RCS, "RCS");
- }};
+ public static final Map<Integer, String> FEATURE_LOG_MAP = Map.of(
+ FEATURE_EMERGENCY_MMTEL, "EMERGENCY_MMTEL",
+ FEATURE_MMTEL, "MMTEL",
+ FEATURE_RCS, "RCS");
/**
* Integer values defining IMS features that are supported in ImsFeature.
@@ -145,11 +143,10 @@
* Used for logging purposes.
* @hide
*/
- public static final Map<Integer, String> STATE_LOG_MAP = new HashMap<Integer, String>() {{
- put(STATE_UNAVAILABLE, "UNAVAILABLE");
- put(STATE_INITIALIZING, "INITIALIZING");
- put(STATE_READY, "READY");
- }};
+ public static final Map<Integer, String> STATE_LOG_MAP = Map.of(
+ STATE_UNAVAILABLE, "UNAVAILABLE",
+ STATE_INITIALIZING, "INITIALIZING",
+ STATE_READY, "READY");
/**
* Integer values defining the result codes that should be returned from
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
index 0f4e122..4bcf5a4 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
@@ -16,14 +16,16 @@
package com.android.test.hwuicompare;
-import java.util.LinkedHashMap;
-import java.util.Map.Entry;
+import static java.util.Map.entry;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.Log;
+import java.util.Map;
+import java.util.Map.Entry;
+
public abstract class DisplayModifier {
// automated tests ignore any combination of operations that don't together return TOTAL_MASK
@@ -76,41 +78,36 @@
};
@SuppressWarnings("serial")
- private static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> gMaps = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>() {
- {
- put("aa", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("true", new DisplayModifier() {
+ private static final Map<String, Map<String, DisplayModifier>> gMaps = Map.of(
+ "aa", Map.of(
+ "true", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setAntiAlias(true);
}
- });
- put("false", new DisplayModifier() {
+ },
+ "false", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setAntiAlias(false);
}
- });
- }
- });
- put("style", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("fill", new DisplayModifier() {
+ }),
+ "style", Map.of(
+ "fill", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
}
- });
- put("stroke", new DisplayModifier() {
+ },
+ "stroke", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- put("fillAndStroke", new DisplayModifier() {
+ },
+ "fillAndStroke", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStyle(Paint.Style.FILL_AND_STROKE);
@@ -118,131 +115,118 @@
@Override
protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- }
- });
- put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("hair", new DisplayModifier() {
+ }),
+ "strokeWidth", Map.of(
+ "hair", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeWidth(0);
}
@Override
protected int mask() { return SWEEP_STROKE_WIDTH_BIT; }
- });
- put("0.3", new DisplayModifier() {
+ },
+ "0.3", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeWidth(0.3f);
}
- });
- put("1", new DisplayModifier() {
+ },
+ "1", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeWidth(1);
}
- });
- put("5", new DisplayModifier() {
+ },
+ "5", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeWidth(5);
}
- });
- put("30", new DisplayModifier() {
+ },
+ "30", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeWidth(30);
}
- });
- }
- });
- put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("butt", new DisplayModifier() {
+ }),
+ "strokeCap", Map.of(
+ "butt", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeCap(Paint.Cap.BUTT);
}
@Override
protected int mask() { return SWEEP_STROKE_CAP_BIT; }
- });
- put("round", new DisplayModifier() {
+ },
+ "round", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeCap(Paint.Cap.ROUND);
}
- });
- put("square", new DisplayModifier() {
+ },
+ "square", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeCap(Paint.Cap.SQUARE);
}
- });
- }
- });
- put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("bevel", new DisplayModifier() {
+ }),
+ "strokeJoin", Map.of(
+ "bevel", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeJoin(Paint.Join.BEVEL);
}
@Override
protected int mask() { return SWEEP_STROKE_JOIN_BIT; }
- });
- put("round", new DisplayModifier() {
+ },
+ "round", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeJoin(Paint.Join.ROUND);
}
- });
- put("miter", new DisplayModifier() {
+ },
+ "miter", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setStrokeJoin(Paint.Join.MITER);
}
- });
+ }),
// TODO: add miter0, miter1 etc to test miter distances
- }
- });
-
- put("transform", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("noTransform", new DisplayModifier() {
+ "transform", Map.of(
+ "noTransform", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {}
@Override
protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- put("rotate5", new DisplayModifier() {
+ },
+ "rotate5", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.rotate(5);
}
- });
- put("rotate45", new DisplayModifier() {
+ },
+ "rotate45", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.rotate(45);
}
- });
- put("rotate90", new DisplayModifier() {
+ },
+ "rotate90", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.rotate(90);
canvas.translate(0, -200);
}
- });
- put("scale2x2", new DisplayModifier() {
+ },
+ "scale2x2", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.scale(2, 2);
}
@Override
protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- put("rot20scl1x4", new DisplayModifier() {
+ },
+ "rot20scl1x4", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.rotate(20);
@@ -250,180 +234,167 @@
}
@Override
protected int mask() { return SWEEP_TRANSFORM_BIT; };
- });
- }
- });
-
- put("shader", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("noShader", new DisplayModifier() {
+ }),
+ "shader", Map.ofEntries(
+ entry("noShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {}
@Override
protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("repeatShader", new DisplayModifier() {
+ }),
+ entry("repeatShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mRepeatShader);
}
@Override
protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("translatedShader", new DisplayModifier() {
+ }),
+ entry("translatedShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mTranslatedShader);
}
- });
- put("scaledShader", new DisplayModifier() {
+ }),
+ entry("scaledShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mScaledShader);
}
- });
- put("horGradient", new DisplayModifier() {
+ }),
+ entry("horGradient", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mHorGradient);
}
- });
- put("diagGradient", new DisplayModifier() {
+ }),
+ entry("diagGradient", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mDiagGradient);
}
@Override
protected int mask() { return SWEEP_SHADER_BIT; };
- });
- put("vertGradient", new DisplayModifier() {
+ }),
+ entry("vertGradient", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mVertGradient);
}
- });
- put("radGradient", new DisplayModifier() {
+ }),
+ entry("radGradient", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mRadGradient);
}
- });
- put("sweepGradient", new DisplayModifier() {
+ }),
+ entry("sweepGradient", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mSweepGradient);
}
- });
- put("composeShader", new DisplayModifier() {
+ }),
+ entry("composeShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mComposeShader);
}
- });
- put("bad composeShader", new DisplayModifier() {
+ }),
+ entry("bad composeShader", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mBadComposeShader);
}
- });
- put("bad composeShader 2", new DisplayModifier() {
+ }),
+ entry("bad composeShader 2", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setShader(ResourceModifiers.instance().mAnotherBadComposeShader);
}
- });
- }
- });
-
- // FINAL MAP: DOES ACTUAL DRAWING
- put("drawing", new LinkedHashMap<String, DisplayModifier>() {
- {
- put("roundRect", new DisplayModifier() {
+ })),
+ "drawing", Map.ofEntries(
+ entry("roundRect", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawRoundRect(gRect, 20, 20, paint);
}
- });
- put("rect", new DisplayModifier() {
+ }),
+ entry("rect", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawRect(gRect, paint);
}
@Override
protected int mask() { return SWEEP_SHADER_BIT | SWEEP_STROKE_CAP_BIT; };
- });
- put("circle", new DisplayModifier() {
+ }),
+ entry("circle", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawCircle(100, 100, 75, paint);
}
- });
- put("oval", new DisplayModifier() {
+ }),
+ entry("oval", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawOval(gRect, paint);
}
- });
- put("lines", new DisplayModifier() {
+ }),
+ entry("lines", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawLines(gLinePts, paint);
}
@Override
protected int mask() { return SWEEP_STROKE_CAP_BIT; };
- });
- put("plusPoints", new DisplayModifier() {
+ }),
+ entry("plusPoints", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawPoints(gPts, paint);
}
- });
- put("text", new DisplayModifier() {
+ }),
+ entry("text", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setTextSize(36);
canvas.drawText("TEXTTEST", 0, 50, paint);
}
- });
- put("shadowtext", new DisplayModifier() {
+ }),
+ entry("shadowtext", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
paint.setTextSize(36);
paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
canvas.drawText("TEXTTEST", 0, 50, paint);
}
- });
- put("bitmapMesh", new DisplayModifier() {
+ }),
+ entry("bitmapMesh", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawBitmapMesh(ResourceModifiers.instance().mBitmap, 3, 3,
ResourceModifiers.instance().mBitmapVertices, 0, null, 0, null);
}
- });
- put("arc", new DisplayModifier() {
+ }),
+ entry("arc", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawArc(gRect, 260, 285, false, paint);
}
@Override
protected int mask() { return SWEEP_STROKE_CAP_BIT; };
- });
- put("arcFromCenter", new DisplayModifier() {
+ }),
+ entry("arcFromCenter", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawArc(gRect, 260, 285, true, paint);
}
@Override
protected int mask() { return SWEEP_STROKE_JOIN_BIT; };
- });
- }
- });
+ })));
// WARNING: DON'T PUT MORE MAPS BELOW THIS
- }
- };
- private static LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
+ private static Map<String, DisplayModifier> getMapAtIndex(int index) {
+ for (Map<String, DisplayModifier> map : gMaps.values()) {
if (index == 0) {
return map;
}
@@ -439,7 +410,7 @@
private static boolean stepInternal(boolean forward) {
int modifierMapIndex = gMaps.size() - 1;
while (modifierMapIndex >= 0) {
- LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
+ Map<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
mIndices[modifierMapIndex] += (forward ? 1 : -1);
if (mIndices[modifierMapIndex] >= 0 && mIndices[modifierMapIndex] < map.size()) {
@@ -471,7 +442,7 @@
private static boolean checkModificationStateMask() {
int operatorMask = 0x0;
int mapIndex = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
+ for (Map<String, DisplayModifier> map : gMaps.values()) {
int displayModifierIndex = mIndices[mapIndex];
for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
if (displayModifierIndex == 0) {
@@ -488,7 +459,7 @@
public static void apply(Paint paint, Canvas canvas) {
int mapIndex = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
+ for (Map<String, DisplayModifier> map : gMaps.values()) {
int displayModifierIndex = mIndices[mapIndex];
for (Entry<String, DisplayModifier> modifierEntry : map.entrySet()) {
if (displayModifierIndex == 0) {
@@ -510,7 +481,7 @@
String[][] keys = new String[gMaps.size()][];
int i = 0;
- for (LinkedHashMap<String, DisplayModifier> map : gMaps.values()) {
+ for (Map<String, DisplayModifier> map : gMaps.values()) {
keys[i] = new String[map.size()];
int j = 0;
for (String key : map.keySet()) {
diff --git a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
index 2ad0da9..8b9c020 100644
--- a/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
+++ b/tests/HierarchyViewerTest/src/com/android/test/hierarchyviewer/ViewDumpParser.java
@@ -58,7 +58,7 @@
Object hash = getProperty(props, "__hash__");
if (name instanceof String && hash instanceof Integer) {
- return String.format(Locale.US, "%s@%x", name, hash);
+ return String.format(Locale.US, "%s@%x", name, (Integer) hash);
} else {
return null;
}
diff --git a/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java b/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
index 4de51fb..43dc9de 100644
--- a/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
+++ b/tests/JankBench/app/src/main/java/com/android/benchmark/app/HomeActivity.java
@@ -140,9 +140,9 @@
handleNextBenchmark();
}
+ @SuppressWarnings("MissingSuperCall") // TODO: Fix me
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
}
private void handleNextBenchmark() {
diff --git a/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java b/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
index c16efbd..d015a56 100644
--- a/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
+++ b/tests/JankBench/app/src/main/java/com/android/benchmark/app/RunLocalBenchmarksActivity.java
@@ -367,6 +367,7 @@
}
}
+ @SuppressWarnings("MissingSuperCall") // TODO: Fix me
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
diff --git a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
index 8afe841..17fa210 100644
--- a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
+++ b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java
@@ -295,8 +295,8 @@
private void updateMirror(Rect displayFrame, float scale) {
if (displayFrame.isEmpty()) {
Rect bounds = mWindowBounds;
- int defaultCropW = Math.round(bounds.width() / 2);
- int defaultCropH = Math.round(bounds.height() / 2);
+ int defaultCropW = bounds.width() / 2;
+ int defaultCropH = bounds.height() / 2;
displayFrame.set(0, 0, defaultCropW, defaultCropH);
}
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 241206d..65b7549 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -24,18 +24,14 @@
static final String KEY_NAME = "name";
static final String KEY_CLASS = "clazz";
- static Map<String,?> make(String name) {
- Map<String,Object> ret = new HashMap<String,Object>();
- ret.put(KEY_NAME, name);
- return ret;
- }
-
- @SuppressWarnings("serial")
- static final ArrayList<Map<String,?>> SAMPLES = new ArrayList<Map<String,?>>() {{
+ static final ArrayList<Map<String, ?>> SAMPLES = new ArrayList<>();
+ static {
for (int i = 1; i < 25; i++) {
- add(make("List Item: " + i));
+ Map<String, Object> sample = new HashMap<String, Object>();
+ sample.put(KEY_NAME, "List Item: " + i);
+ SAMPLES.add(sample);
}
- }};
+ }
Handler mHandler = new Handler();
diff --git a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
index c11b0f3..f85fb0f 100644
--- a/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
+++ b/tests/SmokeTestApps/src/com/android/smoketest/triggers/CrashyApp.java
@@ -30,6 +30,7 @@
setContentView(tv);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public void onResume() {
((String) null).length();
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index f924b2e..ad06830 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -637,8 +637,7 @@
final BroadcastReceiver receiver = getPackageChangeReceiver();
verify(mMockContext).registerReceiver(any(), argThat(filter -> {
- return filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
- && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED);
+ return filter.hasAction(Intent.ACTION_PACKAGE_REMOVED);
}), any(), any());
receiver.onReceive(mMockContext, new Intent(Intent.ACTION_PACKAGE_REMOVED));
diff --git a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java b/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
index a750696..5012622 100644
--- a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
@@ -117,13 +117,12 @@
private static final byte[] TEST_PSK =
new byte[]{'T', 'e', 's', 't'};
- private static final Set<Integer> SCAN_FREQ_SET =
- new HashSet<Integer>() {{
- add(2410);
- add(2450);
- add(5050);
- add(5200);
- }};
+ private static final Set<Integer> SCAN_FREQ_SET = Set.of(
+ 2410,
+ 2450,
+ 5050,
+ 5200);
+
private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\"";
private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\"";
private static final int[] TEST_FREQUENCIES_1 = {};
@@ -131,13 +130,11 @@
private static final MacAddress TEST_RAW_MAC_BYTES = MacAddress.fromBytes(
new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05});
- private static final List<byte[]> SCAN_HIDDEN_NETWORK_SSID_LIST =
- new ArrayList<byte[]>() {{
- add(LocalNativeUtil.byteArrayFromArrayList(
- LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_1)));
- add(LocalNativeUtil.byteArrayFromArrayList(
- LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
- }};
+ private static final List<byte[]> SCAN_HIDDEN_NETWORK_SSID_LIST = List.of(
+ LocalNativeUtil.byteArrayFromArrayList(
+ LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_1)),
+ LocalNativeUtil.byteArrayFromArrayList(
+ LocalNativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
private static final PnoSettings TEST_PNO_SETTINGS = new PnoSettings();
static {