summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java11
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobParameters.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java115
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java45
-rw-r--r--core/api/module-lib-current.txt1
-rw-r--r--core/api/system-current.txt2
-rw-r--r--core/api/test-current.txt14
-rw-r--r--core/java/android/app/ActivityManager.java30
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/app/IUserSwitchObserver.aidl1
-rw-r--r--core/java/android/app/UserSwitchObserver.java3
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java2
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/provider/Settings.java33
-rw-r--r--core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java6
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java27
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl3
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--graphics/java/android/graphics/ImageDecoder.java48
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java52
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java25
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java20
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/DataServiceUtils.java32
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/SubscriptionInfoEntity.java50
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java4
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java2
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/res/values/integers.xml8
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java80
-rw-r--r--services/companion/java/com/android/server/companion/virtual/InputController.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java39
-rw-r--r--services/core/java/com/android/server/am/UserController.java11
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java32
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java12
-rw-r--r--services/core/java/com/android/server/pm/ComputerEngine.java1
-rw-r--r--services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java12
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java24
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java3
-rw-r--r--services/core/java/com/android/server/wm/Transition.java13
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java9
-rw-r--r--services/core/java/com/android/server/wm/VrController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java56
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java63
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java34
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java122
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java2
-rw-r--r--services/tests/uiservicestests/AndroidManifest.xml1
-rw-r--r--services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java11
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java67
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java107
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java9
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java36
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java8
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java5
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java7
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java20
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java1
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java81
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java105
74 files changed, 1048 insertions, 623 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 805dfafe5923..37ceb091f035 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1382,6 +1382,12 @@ public class JobInfo implements Parcelable {
* Calling this method will override any requirements previously defined
* by {@link #setRequiredNetwork(NetworkRequest)}; you typically only
* want to call one of these methods.
+ *
+ * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * an app must hold the {@link android.Manifest.permission#INTERNET} and
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} permissions to
+ * schedule a job that requires a network.
+ *
* <p class="note">
* When your job executes in
* {@link JobService#onStartJob(JobParameters)}, be sure to use the
@@ -1438,6 +1444,11 @@ public class JobInfo implements Parcelable {
* otherwise you'll use the default network which may not meet this
* constraint.
*
+ * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * an app must hold the {@link android.Manifest.permission#INTERNET} and
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} permissions to
+ * schedule a job that requires a network.
+ *
* @param networkRequest The detailed description of the kind of network
* this job requires, or {@code null} if no specific kind of
* network is required. Defining a {@link NetworkSpecifier}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 32502eddc9f8..bf4f9a83b99c 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -481,6 +481,10 @@ public class JobParameters implements Parcelable {
* such as allowing a {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over
* a metered network when there is a surplus of metered data available.
*
+ * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * this will return {@code null} if the app does not hold the permissions specified in
+ * {@link JobInfo.Builder#setRequiredNetwork(NetworkRequest)}.
+ *
* @return the network that should be used to perform any network requests
* for this job, or {@code null} if this job didn't set any required
* network type or if the job executed when there was no available network to use.
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 d94993d64995..d06596fa18aa 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import android.Manifest;
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -190,6 +191,14 @@ public class JobSchedulerService extends com.android.server.SystemService
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
private static final long REQUIRE_NETWORK_CONSTRAINT_FOR_NETWORK_JOB_WORK_ITEMS = 241104082L;
+ /**
+ * Require the app to have the INTERNET and ACCESS_NETWORK_STATE permissions when scheduling
+ * a job with a connectivity constraint.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ static final long REQUIRE_NETWORK_PERMISSIONS_FOR_CONNECTIVITY_JOBS = 271850009L;
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public static Clock sSystemClock = Clock.systemUTC();
@@ -299,6 +308,14 @@ public class JobSchedulerService extends com.android.server.SystemService
private final RemoteCallbackList<IUserVisibleJobObserver> mUserVisibleJobObservers =
new RemoteCallbackList<>();
+ /**
+ * Cache of grant status of permissions, keyed by UID->PID->permission name. A missing value
+ * means the state has not been queried.
+ */
+ @GuardedBy("mPermissionCache")
+ private final SparseArray<SparseArrayMap<String, Boolean>> mPermissionCache =
+ new SparseArray<>();
+
private final CountQuotaTracker mQuotaTracker;
private static final String QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG = ".schedulePersisted()";
private static final String QUOTA_TRACKER_SCHEDULE_LOGGED =
@@ -1042,6 +1059,10 @@ public class JobSchedulerService extends com.android.server.SystemService
final int pkgUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ synchronized (mPermissionCache) {
+ // Something changed. Better clear the cached permission set.
+ mPermissionCache.remove(pkgUid);
+ }
// Purge the app's jobs if the whole package was just disabled. When this is
// the case the component name will be a bare package name.
if (pkgName != null && pkgUid != -1) {
@@ -1106,17 +1127,19 @@ public class JobSchedulerService extends com.android.server.SystemService
Slog.w(TAG, "PACKAGE_CHANGED for " + pkgName + " / uid " + pkgUid);
}
} else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ synchronized (mPermissionCache) {
+ // Something changed. Better clear the cached permission set.
+ mPermissionCache.remove(pkgUid);
+ }
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
synchronized (mLock) {
- mUidToPackageCache.remove(uid);
- }
- } else {
- synchronized (mJobSchedulerStub.mPersistCache) {
- mJobSchedulerStub.mPersistCache.remove(pkgUid);
+ mUidToPackageCache.remove(pkgUid);
}
}
} else if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) {
+ synchronized (mPermissionCache) {
+ mPermissionCache.remove(pkgUid);
+ }
if (DEBUG) {
Slog.d(TAG, "Removing jobs for " + pkgName + " (uid=" + pkgUid + ")");
}
@@ -1155,6 +1178,14 @@ public class JobSchedulerService extends com.android.server.SystemService
}
}
mConcurrencyManager.onUserRemoved(userId);
+ synchronized (mPermissionCache) {
+ for (int u = mPermissionCache.size() - 1; u >= 0; --u) {
+ final int uid = mPermissionCache.keyAt(u);
+ if (userId == UserHandle.getUserId(uid)) {
+ mPermissionCache.removeAt(u);
+ }
+ }
+ }
} else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
// Has this package scheduled any jobs, such that we will take action
// if it were to be force-stopped?
@@ -3748,18 +3779,38 @@ public class JobSchedulerService extends com.android.server.SystemService
}
/**
+ * Returns whether the app has the permission granted.
+ * This currently only works for normal permissions and <b>DOES NOT</b> work for runtime
+ * permissions.
+ * TODO: handle runtime permissions
+ */
+ private boolean hasPermission(int uid, int pid, @NonNull String permission) {
+ synchronized (mPermissionCache) {
+ SparseArrayMap<String, Boolean> pidPermissions = mPermissionCache.get(uid);
+ if (pidPermissions == null) {
+ pidPermissions = new SparseArrayMap<>();
+ mPermissionCache.put(uid, pidPermissions);
+ }
+ final Boolean cached = pidPermissions.get(pid, permission);
+ if (cached != null) {
+ return cached;
+ }
+
+ final int result = getContext().checkPermission(permission, pid, uid);
+ final boolean permissionGranted = (result == PackageManager.PERMISSION_GRANTED);
+ pidPermissions.add(pid, permission, permissionGranted);
+ return permissionGranted;
+ }
+ }
+
+ /**
* Binder stub trampoline implementation
*/
final class JobSchedulerStub extends IJobScheduler.Stub {
- /**
- * Cache determination of whether a given app can persist jobs
- * key is uid of the calling app; value is undetermined/true/false
- */
- private final SparseArray<Boolean> mPersistCache = new SparseArray<Boolean>();
-
// Enforce that only the app itself (or shared uid participant) can schedule a
// job that runs one of the app's services, as well as verifying that the
// named service properly requires the BIND_JOB_SERVICE permission
+ // TODO(141645789): merge enforceValidJobRequest() with validateJob()
private void enforceValidJobRequest(int uid, int pid, JobInfo job) {
final PackageManager pm = getContext()
.createContextAsUser(UserHandle.getUserHandleForUid(uid), 0)
@@ -3784,31 +3835,33 @@ public class JobSchedulerService extends com.android.server.SystemService
throw new IllegalArgumentException(
"Tried to schedule job for non-existent component: " + service);
}
+ // If we get this far we're good to go; all we need to do now is check
+ // whether the app is allowed to persist its scheduled work.
if (job.isPersisted() && !canPersistJobs(pid, uid)) {
throw new IllegalArgumentException("Requested job cannot be persisted without"
+ " holding android.permission.RECEIVE_BOOT_COMPLETED permission");
}
+ if (job.getRequiredNetwork() != null
+ && CompatChanges.isChangeEnabled(
+ REQUIRE_NETWORK_PERMISSIONS_FOR_CONNECTIVITY_JOBS, uid)) {
+ // All networking, including with the local network and even local to the device,
+ // requires the INTERNET permission.
+ if (!hasPermission(uid, pid, Manifest.permission.INTERNET)) {
+ throw new SecurityException(Manifest.permission.INTERNET
+ + " required for jobs with a connectivity constraint");
+ }
+ if (!hasPermission(uid, pid, Manifest.permission.ACCESS_NETWORK_STATE)) {
+ throw new SecurityException(Manifest.permission.ACCESS_NETWORK_STATE
+ + " required for jobs with a connectivity constraint");
+ }
+ }
}
private boolean canPersistJobs(int pid, int uid) {
- // If we get this far we're good to go; all we need to do now is check
- // whether the app is allowed to persist its scheduled work.
- final boolean canPersist;
- synchronized (mPersistCache) {
- Boolean cached = mPersistCache.get(uid);
- if (cached != null) {
- canPersist = cached.booleanValue();
- } else {
- // Persisting jobs is tantamount to running at boot, so we permit
- // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
- // permission
- int result = getContext().checkPermission(
- android.Manifest.permission.RECEIVE_BOOT_COMPLETED, pid, uid);
- canPersist = (result == PackageManager.PERMISSION_GRANTED);
- mPersistCache.put(uid, canPersist);
- }
- }
- return canPersist;
+ // Persisting jobs is tantamount to running at boot, so we permit
+ // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
+ // permission
+ return hasPermission(uid, pid, Manifest.permission.RECEIVE_BOOT_COMPLETED);
}
private int validateJob(@NonNull JobInfo job, int callingUid, int callingPid,
@@ -4027,6 +4080,8 @@ public class JobSchedulerService extends com.android.server.SystemService
+ " not permitted to schedule jobs for other apps");
}
+ enforceValidJobRequest(callerUid, callerPid, job);
+
int result = validateJob(job, callerUid, callerPid, userId, packageName, null);
if (result != JobScheduler.RESULT_SUCCESS) {
return result;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index b080bf31fed4..1e2ef7755664 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -21,6 +21,7 @@ import static android.app.job.JobInfo.getPriorityString;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import android.Manifest;
import android.annotation.BytesLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -39,6 +40,7 @@ import android.compat.annotation.EnabledAfter;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.ServiceConnection;
import android.net.Network;
import android.net.Uri;
@@ -339,12 +341,13 @@ public final class JobServiceContext implements ServiceConnection {
job.changedAuthorities.toArray(triggeredAuthorities);
}
final JobInfo ji = job.getJob();
+ final Network passedNetwork = canGetNetworkInformation(job) ? job.network : null;
mParams = new JobParameters(mRunningCallback, job.getNamespace(), job.getJobId(),
ji.getExtras(),
ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(),
isDeadlineExpired, job.shouldTreatAsExpeditedJob(),
job.shouldTreatAsUserInitiatedJob(), triggeredUris, triggeredAuthorities,
- job.network);
+ passedNetwork);
mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis();
mMinExecutionGuaranteeMillis = mService.getMinJobExecutionGuaranteeMs(job);
mMaxExecutionTimeMillis =
@@ -504,6 +507,37 @@ public final class JobServiceContext implements ServiceConnection {
}
}
+ private boolean canGetNetworkInformation(@NonNull JobStatus job) {
+ if (job.getJob().getRequiredNetwork() == null) {
+ // The job never had a network constraint, so we're not going to give it a network
+ // object. Add this check as an early return to avoid wasting cycles doing permission
+ // checks for this job.
+ return false;
+ }
+ // The calling app is doing the work, so use its UID, not the source UID.
+ final int uid = job.getUid();
+ if (CompatChanges.isChangeEnabled(
+ JobSchedulerService.REQUIRE_NETWORK_PERMISSIONS_FOR_CONNECTIVITY_JOBS, uid)) {
+ final String pkgName = job.getServiceComponent().getPackageName();
+ if (!hasPermissionForDelivery(uid, pkgName, Manifest.permission.INTERNET)) {
+ return false;
+ }
+ if (!hasPermissionForDelivery(uid, pkgName, Manifest.permission.ACCESS_NETWORK_STATE)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean hasPermissionForDelivery(int uid, @NonNull String pkgName,
+ @NonNull String permission) {
+ final int result = PermissionChecker.checkPermissionForDataDelivery(mContext, permission,
+ PermissionChecker.PID_UNKNOWN, uid, pkgName, /* attributionTag */ null,
+ "network info via JS");
+ return result == PermissionChecker.PERMISSION_GRANTED;
+ }
+
@EconomicPolicy.AppAction
private static int getStartActionId(@NonNull JobStatus job) {
switch (job.getEffectivePriority()) {
@@ -603,6 +637,15 @@ public final class JobServiceContext implements ServiceConnection {
}
void informOfNetworkChangeLocked(Network newNetwork) {
+ if (newNetwork != null && mRunningJob != null && !canGetNetworkInformation(mRunningJob)) {
+ // The app can't get network information, so there's no point informing it of network
+ // changes. This case may happen if an app had scheduled network job and then
+ // started targeting U+ without requesting the required network permissions.
+ if (DEBUG) {
+ Slog.d(TAG, "Skipping network change call because of missing permissions");
+ }
+ return;
+ }
if (mVerb != VERB_EXECUTING) {
Slog.w(TAG, "Sending onNetworkChanged for a job that isn't started. " + mRunningJob);
if (mVerb == VERB_BINDING || mVerb == VERB_STARTING) {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 58f78aa4fc15..c1f6219025f9 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -18,6 +18,7 @@ package android.app {
public class ActivityManager {
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index b21028464426..fbc69e34a644 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -33,7 +33,6 @@ package android {
field public static final String ADD_TRUSTED_DISPLAY = "android.permission.ADD_TRUSTED_DISPLAY";
field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
- field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG";
field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS";
field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES";
@@ -380,6 +379,7 @@ package android {
field public static final String WIFI_SET_DEVICE_MOBILITY_STATE = "android.permission.WIFI_SET_DEVICE_MOBILITY_STATE";
field public static final String WIFI_UPDATE_COEX_UNSAFE_CHANNELS = "android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS";
field public static final String WIFI_UPDATE_USABILITY_STATS_SCORE = "android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE";
+ field public static final String WRITE_ALLOWLISTED_DEVICE_CONFIG = "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG";
field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
field public static final String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE";
field public static final String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1a8ebb15663b..ed36f1c3d99d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -5,7 +5,6 @@ package android {
field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
- field public static final String ALLOWLISTED_WRITE_DEVICE_CONFIG = "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG";
field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
field public static final String BIND_CELL_BROADCAST_SERVICE = "android.permission.BIND_CELL_BROADCAST_SERVICE";
@@ -55,6 +54,7 @@ package android {
field public static final String TEST_INPUT_METHOD = "android.permission.TEST_INPUT_METHOD";
field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS";
+ field public static final String WRITE_ALLOWLISTED_DEVICE_CONFIG = "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG";
field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
@@ -131,11 +131,13 @@ package android.app {
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public int[] getDisplayIdsForStartingVisibleBackgroundUsers();
method public long getTotalRam();
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]);
method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessCapabilities(int);
method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessState(int);
method public void holdLock(android.os.IBinder, int);
method public static boolean isHighEndGfx();
method public void notifySystemPropertiesChanged();
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors();
method public static void resumeAppSwitches() throws android.os.RemoteException;
@@ -143,6 +145,7 @@ package android.app {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void setStopUserOnSwitch(int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean startUserInBackgroundVisibleOnDisplay(int, int);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
@@ -166,6 +169,12 @@ package android.app {
method @Nullable public String getIconResourcePackage();
}
+ public static interface ActivityManager.UidFrozenStateChangedCallback {
+ method public void onUidFrozenStateChanged(@NonNull int[], @NonNull int[]);
+ field public static final int UID_FROZEN_STATE_FROZEN = 1; // 0x1
+ field public static final int UID_FROZEN_STATE_UNFROZEN = 2; // 0x2
+ }
+
public class ActivityOptions extends android.app.ComponentOptions {
method public boolean isEligibleForLegacyPermissionPrompt();
method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
@@ -2607,7 +2616,6 @@ package android.provider {
field @Deprecated public static final String NOTIFICATION_BUBBLES = "notification_bubbles";
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
- field public static final String STYLUS_HANDWRITING_ENABLED = "stylus_handwriting_enabled";
field public static final String USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
@@ -2639,6 +2647,8 @@ package android.provider {
field public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION = "show_first_crash_dialog_dev_option";
field public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
field public static final String STYLUS_BUTTONS_ENABLED = "stylus_buttons_enabled";
+ field public static final int STYLUS_HANDWRITING_DEFAULT_VALUE = 1; // 0x1
+ field public static final String STYLUS_HANDWRITING_ENABLED = "stylus_handwriting_enabled";
field @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 929c07bc1dc5..21097079540d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -256,6 +256,7 @@ public class ActivityManager {
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
public interface UidFrozenStateChangedCallback {
/**
* Indicates that the UID was frozen.
@@ -263,6 +264,7 @@ public class ActivityManager {
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
int UID_FROZEN_STATE_FROZEN = 1;
/**
@@ -271,6 +273,7 @@ public class ActivityManager {
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
int UID_FROZEN_STATE_UNFROZEN = 2;
/**
@@ -296,6 +299,7 @@ public class ActivityManager {
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
void onUidFrozenStateChanged(@NonNull int[] uids,
@NonNull @UidFrozenState int[] frozenStates);
}
@@ -315,6 +319,7 @@ public class ActivityManager {
*/
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
public void registerUidFrozenStateChangedCallback(
@NonNull Executor executor,
@NonNull UidFrozenStateChangedCallback callback) {
@@ -346,6 +351,7 @@ public class ActivityManager {
*/
@RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
public void unregisterUidFrozenStateChangedCallback(
@NonNull UidFrozenStateChangedCallback callback) {
Preconditions.checkNotNull(callback, "callback cannot be null");
@@ -363,6 +369,30 @@ public class ActivityManager {
}
/**
+ * Query the frozen state of a list of UIDs.
+ *
+ * @param uids the array of UIDs which the client would like to know the frozen state of.
+ * @return An array containing the frozen state for each requested UID, by index. Will be set
+ * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN}
+ * if the UID is frozen. If the UID is not frozen or not found,
+ * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN}
+ * will be set.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public @NonNull @UidFrozenStateChangedCallback.UidFrozenState
+ int[] getUidFrozenState(@NonNull int[] uids) {
+ try {
+ return getService().getUidFrozenState(uids);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code
* <meta-data>}</a> name for a 'home' Activity that declares a package that is to be
* uninstalled in lieu of the declaring one. The package named here must be
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 97d45623d3da..91eb4c44cda5 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -882,4 +882,6 @@ interface IActivityManager {
void registerUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
void unregisterUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+ int[] getUidFrozenState(in int[] uids);
}
diff --git a/core/java/android/app/IUserSwitchObserver.aidl b/core/java/android/app/IUserSwitchObserver.aidl
index 234da8f36e96..cfdb426d6026 100644
--- a/core/java/android/app/IUserSwitchObserver.aidl
+++ b/core/java/android/app/IUserSwitchObserver.aidl
@@ -20,6 +20,7 @@ import android.os.IRemoteCallback;
/** {@hide} */
oneway interface IUserSwitchObserver {
+ void onBeforeUserSwitching(int newUserId);
void onUserSwitching(int newUserId, IRemoteCallback reply);
void onUserSwitchComplete(int newUserId);
void onForegroundProfileSwitch(int newProfileId);
diff --git a/core/java/android/app/UserSwitchObserver.java b/core/java/android/app/UserSwitchObserver.java
index 6abc4f09ba38..727799a1f948 100644
--- a/core/java/android/app/UserSwitchObserver.java
+++ b/core/java/android/app/UserSwitchObserver.java
@@ -30,6 +30,9 @@ public class UserSwitchObserver extends IUserSwitchObserver.Stub {
}
@Override
+ public void onBeforeUserSwitching(int newUserId) throws RemoteException {}
+
+ @Override
public void onUserSwitching(int newUserId, IRemoteCallback reply) throws RemoteException {
if (reply != null) {
reply.sendResult(null);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 924a7c659b08..bad6c77a17f3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -15775,7 +15775,7 @@ public class DevicePolicyManager {
throwIfParentInstance("setApplicationExemptions");
if (mService != null) {
try {
- mService.setApplicationExemptions(packageName,
+ mService.setApplicationExemptions(mContext.getPackageName(), packageName,
ArrayUtils.convertToIntArray(new ArraySet<>(exemptions)));
} catch (ServiceSpecificException e) {
switch (e.errorCode) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index e202ac2c9245..8d508c0fb79d 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -591,7 +591,7 @@ interface IDevicePolicyManager {
List<UserHandle> getPolicyManagedProfiles(in UserHandle userHandle);
- void setApplicationExemptions(String packageName, in int[]exemptions);
+ void setApplicationExemptions(String callerPackage, String packageName, in int[]exemptions);
int[] getApplicationExemptions(String packageName);
void setMtePolicy(int flag, String callerPackageName);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7ae280fd7d90..c473d3f81823 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7113,6 +7113,28 @@ public final class Settings {
"input_method_selector_visibility";
/**
+ * Toggle for enabling stylus handwriting. When enabled, current Input method receives
+ * stylus {@link MotionEvent}s if an {@link Editor} is focused.
+ *
+ * @see #STYLUS_HANDWRITING_DEFAULT_VALUE
+ * @hide
+ */
+ @TestApi
+ @Readable
+ @SuppressLint("NoSettingsProvider")
+ public static final String STYLUS_HANDWRITING_ENABLED = "stylus_handwriting_enabled";
+
+ /**
+ * Default value for {@link #STYLUS_HANDWRITING_ENABLED}.
+ *
+ * @hide
+ */
+ @TestApi
+ @Readable
+ @SuppressLint("NoSettingsProvider")
+ public static final int STYLUS_HANDWRITING_DEFAULT_VALUE = 1;
+
+ /**
* The currently selected voice interaction service flattened ComponentName.
* @hide
*/
@@ -16482,17 +16504,6 @@ public final class Settings {
public static final String AUTOFILL_MAX_VISIBLE_DATASETS = "autofill_max_visible_datasets";
/**
- * Toggle for enabling stylus handwriting. When enabled, current Input method receives
- * stylus {@link MotionEvent}s if an {@link Editor} is focused.
- *
- * @hide
- */
- @TestApi
- @Readable
- @SuppressLint("NoSettingsProvider")
- public static final String STYLUS_HANDWRITING_ENABLED = "stylus_handwriting_enabled";
-
- /**
* Indicates whether a stylus has ever been used on the device.
*
* @hide
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index d84acc03826b..ce2c18080b91 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -508,6 +508,7 @@ final class IInputMethodManagerGlobalInvoker {
@AnyThread
static void prepareStylusHandwritingDelegation(
@NonNull IInputMethodClient client,
+ @UserIdInt int userId,
@NonNull String delegatePackageName,
@NonNull String delegatorPackageName) {
final IInputMethodManager service = getService();
@@ -516,7 +517,7 @@ final class IInputMethodManagerGlobalInvoker {
}
try {
service.prepareStylusHandwritingDelegation(
- client, delegatePackageName, delegatorPackageName);
+ client, userId, delegatePackageName, delegatorPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -525,6 +526,7 @@ final class IInputMethodManagerGlobalInvoker {
@AnyThread
static boolean acceptStylusHandwritingDelegation(
@NonNull IInputMethodClient client,
+ @UserIdInt int userId,
@NonNull String delegatePackageName,
@NonNull String delegatorPackageName) {
final IInputMethodManager service = getService();
@@ -533,7 +535,7 @@ final class IInputMethodManagerGlobalInvoker {
}
try {
return service.acceptStylusHandwritingDelegation(
- client, delegatePackageName, delegatorPackageName);
+ client, userId, delegatePackageName, delegatorPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 36d2b8a89779..515b95cd951d 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1553,9 +1553,7 @@ public final class InputMethodManager {
if (fallbackContext == null) {
return false;
}
- if (!isStylusHandwritingEnabled(fallbackContext)) {
- return false;
- }
+
return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(userId);
}
@@ -2244,11 +2242,6 @@ public final class InputMethodManager {
}
boolean useDelegation = !TextUtils.isEmpty(delegatorPackageName);
- if (!isStylusHandwritingEnabled(view.getContext())) {
- Log.w(TAG, "Stylus handwriting pref is disabled. "
- + "Ignoring calls to start stylus handwriting.");
- return false;
- }
checkFocus();
synchronized (mH) {
@@ -2264,7 +2257,8 @@ public final class InputMethodManager {
}
if (useDelegation) {
return IInputMethodManagerGlobalInvoker.acceptStylusHandwritingDelegation(
- mClient, view.getContext().getOpPackageName(), delegatorPackageName);
+ mClient, UserHandle.myUserId(), view.getContext().getOpPackageName(),
+ delegatorPackageName);
} else {
IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
}
@@ -2272,15 +2266,6 @@ public final class InputMethodManager {
}
}
- private boolean isStylusHandwritingEnabled(@NonNull Context context) {
- if (Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.STYLUS_HANDWRITING_ENABLED, 0) == 0) {
- Log.d(TAG, "Stylus handwriting pref is disabled.");
- return false;
- }
- return true;
- }
-
/**
* Prepares delegation of starting stylus handwriting session to a different editor in same
* or different window than the view on which initial handwriting stroke was detected.
@@ -2344,13 +2329,9 @@ public final class InputMethodManager {
fallbackImm.prepareStylusHandwritingDelegation(delegatorView, delegatePackageName);
}
- if (!isStylusHandwritingEnabled(delegatorView.getContext())) {
- Log.w(TAG, "Stylus handwriting pref is disabled. "
- + "Ignoring prepareStylusHandwritingDelegation().");
- return;
- }
IInputMethodManagerGlobalInvoker.prepareStylusHandwritingDelegation(
mClient,
+ UserHandle.myUserId(),
delegatePackageName,
delegatorView.getContext().getOpPackageName());
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 593f3dbb99de..d56a06fbd127 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11497,7 +11497,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
changed = true;
}
- if (requestRectWithoutFocus && isFocused()) {
+ if (requestRectWithoutFocus || isFocused()) {
// This offsets because getInterestingRect() is in terms of viewport coordinates, but
// requestRectangleOnScreen() is in terms of content coordinates.
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 9a4610e8c0a1..549169388e45 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -150,12 +150,13 @@ interface IInputMethodManager {
/** Prepares delegation of starting stylus handwriting session to a different editor **/
void prepareStylusHandwritingDelegation(in IInputMethodClient client,
+ in int userId,
in String delegatePackageName,
in String delegatorPackageName);
/** Accepts and starts a stylus handwriting session for the delegate view **/
boolean acceptStylusHandwritingDelegation(in IInputMethodClient client,
- in String delegatePackageName, in String delegatorPackageName);
+ in int userId, in String delegatePackageName, in String delegatorPackageName);
/** Returns {@code true} if currently selected IME supports Stylus handwriting. */
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 393e7785b446..81b1f21e286d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4205,14 +4205,14 @@
<permission android:name="android.permission.WRITE_DEVICE_CONFIG"
android:protectionLevel="signature|verifier|configurator"/>
- <!-- @SystemApi @TestApi @hide Allows an application to read/write sync disabled mode config.
+ <!-- @SystemApi @TestApi @hide Allows an application to modify only allowlisted settings.
<p>Not for use by third-party applications. -->
- <permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"
+ <permission android:name="android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG"
android:protectionLevel="signature|verifier|configurator"/>
- <!-- @SystemApi @TestApi @hide Allows an application to modify only allowlisted settings.
+ <!-- @SystemApi @TestApi @hide Allows an application to read/write sync disabled mode config.
<p>Not for use by third-party applications. -->
- <permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG"
+ <permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"
android:protectionLevel="signature|verifier|configurator"/>
<!-- @SystemApi @hide Allows an application to read config settings.
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 22462eb11a8f..51f99ec637da 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -38,11 +38,8 @@ import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.net.Uri;
import android.os.Build;
-import android.os.SystemProperties;
import android.os.Trace;
import android.system.ErrnoException;
import android.system.Os;
@@ -931,8 +928,6 @@ public final class ImageDecoder implements AutoCloseable {
case "image/x-pentax-pef":
case "image/x-samsung-srw":
return true;
- case "image/avif":
- return isP010SupportedForAV1();
default:
return false;
}
@@ -2068,49 +2063,6 @@ public final class ImageDecoder implements AutoCloseable {
return decodeBitmapImpl(src, null);
}
- private static boolean sIsP010SupportedForAV1 = false;
- private static boolean sIsP010SupportedForAV1Initialized = false;
-
- /**
- * Checks if the device supports decoding 10-bit AV1.
- */
- private static boolean isP010SupportedForAV1() {
- if (sIsP010SupportedForAV1Initialized) {
- return sIsP010SupportedForAV1;
- }
-
- sIsP010SupportedForAV1Initialized = true;
-
- if (hasHardwareDecoder("video/av01")) {
- sIsP010SupportedForAV1 = true;
- return true;
- }
-
- sIsP010SupportedForAV1 = SystemProperties.getInt("ro.product.first_api_level", 0) >=
- Build.VERSION_CODES.S;
- return sIsP010SupportedForAV1;
- }
-
- /**
- * Checks if the device has hardware decoder for the target mime type.
- */
- private static boolean hasHardwareDecoder(String mime) {
- final MediaCodecList sMCL = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- for (MediaCodecInfo info : sMCL.getCodecInfos()) {
- if (info.isEncoder() == false && info.isHardwareAccelerated()) {
- try {
- if (info.getCapabilitiesForType(mime) != null) {
- return true;
- }
- } catch (IllegalArgumentException e) {
- // mime is not supported
- return false;
- }
- }
- }
- return false;
- }
-
/**
* Private method called by JNI.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 4805ed39e1a2..5f2b63089009 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -656,6 +656,13 @@ public class Bubble implements BubbleViewProvider {
}
/**
+ * Whether this bubble is conversation
+ */
+ public boolean isConversation() {
+ return null != mShortcutInfo;
+ }
+
+ /**
* Sets whether this notification should be suppressed in the shade.
*/
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index deb4fd5f19bb..66241628fc77 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -33,7 +33,6 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
-import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -575,7 +574,7 @@ public class BubbleStackView extends FrameLayout
if (maybeShowStackEdu()) {
mShowedUserEducationInTouchListenerActive = true;
return true;
- } else if (isStackEduShowing()) {
+ } else if (isStackEduVisible()) {
mStackEduView.hide(false /* fromExpansion */);
}
@@ -651,7 +650,7 @@ public class BubbleStackView extends FrameLayout
mExpandedAnimationController.dragBubbleOut(
v, viewInitialX + dx, viewInitialY + dy);
} else {
- if (isStackEduShowing()) {
+ if (isStackEduVisible()) {
mStackEduView.hide(false /* fromExpansion */);
}
mStackAnimationController.moveStackFromTouch(
@@ -733,8 +732,7 @@ public class BubbleStackView extends FrameLayout
@Override
public void onMove(float dx, float dy) {
- if ((mManageEduView != null && mManageEduView.getVisibility() == VISIBLE)
- || isStackEduShowing()) {
+ if (isManageEduVisible() || isStackEduVisible()) {
return;
}
@@ -996,7 +994,7 @@ public class BubbleStackView extends FrameLayout
mStackAnimationController.updateResources();
mBubbleOverflow.updateResources();
- if (!isStackEduShowing() && mRelativeStackPositionBeforeRotation != null) {
+ if (!isStackEduVisible() && mRelativeStackPositionBeforeRotation != null) {
mStackAnimationController.setStackPosition(
mRelativeStackPositionBeforeRotation);
mRelativeStackPositionBeforeRotation = null;
@@ -1046,9 +1044,9 @@ public class BubbleStackView extends FrameLayout
setOnClickListener(view -> {
if (mShowingManage) {
showManageMenu(false /* show */);
- } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ } else if (isManageEduVisible()) {
mManageEduView.hide();
- } else if (isStackEduShowing()) {
+ } else if (isStackEduVisible()) {
mStackEduView.hide(false /* isExpanding */);
} else if (mBubbleData.isExpanded()) {
mBubbleData.setExpanded(false);
@@ -1247,10 +1245,19 @@ public class BubbleStackView extends FrameLayout
}
/**
+ * Whether the selected bubble is conversation bubble
+ */
+ private boolean isConversationBubble() {
+ BubbleViewProvider bubble = mBubbleData.getSelectedBubble();
+ return bubble instanceof Bubble && ((Bubble) bubble).isConversation();
+ }
+
+ /**
* Whether the educational view should show for the expanded view "manage" menu.
*/
private boolean shouldShowManageEdu() {
- if (ActivityManager.isRunningInTestHarness()) {
+ if (!isConversationBubble()) {
+ // We only show user education for conversation bubbles right now
return false;
}
final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION);
@@ -1273,11 +1280,17 @@ public class BubbleStackView extends FrameLayout
mManageEduView.show(mExpandedBubble.getExpandedView());
}
+ @VisibleForTesting
+ public boolean isManageEduVisible() {
+ return mManageEduView != null && mManageEduView.getVisibility() == VISIBLE;
+ }
+
/**
* Whether education view should show for the collapsed stack.
*/
private boolean shouldShowStackEdu() {
- if (ActivityManager.isRunningInTestHarness()) {
+ if (!isConversationBubble()) {
+ // We only show user education for conversation bubbles right now
return false;
}
final boolean seen = getPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION);
@@ -1310,13 +1323,14 @@ public class BubbleStackView extends FrameLayout
return mStackEduView.show(mPositioner.getDefaultStartPosition());
}
- private boolean isStackEduShowing() {
+ @VisibleForTesting
+ public boolean isStackEduVisible() {
return mStackEduView != null && mStackEduView.getVisibility() == VISIBLE;
}
// Recreates & shows the education views. Call when a theme/config change happens.
private void updateUserEdu() {
- if (isStackEduShowing()) {
+ if (isStackEduVisible()) {
removeView(mStackEduView);
mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController);
addView(mStackEduView);
@@ -1325,7 +1339,7 @@ public class BubbleStackView extends FrameLayout
mStackAnimationController.setStackPosition(mPositioner.getDefaultStartPosition());
mStackEduView.show(mPositioner.getDefaultStartPosition());
}
- if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ if (isManageEduVisible()) {
removeView(mManageEduView);
mManageEduView = new ManageEducationView(mContext, mPositioner);
addView(mManageEduView);
@@ -1429,7 +1443,7 @@ public class BubbleStackView extends FrameLayout
mStackAnimationController.updateResources();
mDismissView.updateResources();
mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2);
- if (!isStackEduShowing()) {
+ if (!isStackEduVisible()) {
mStackAnimationController.setStackPosition(
new RelativeStackPosition(
mPositioner.getRestingPosition(),
@@ -2013,7 +2027,7 @@ public class BubbleStackView extends FrameLayout
if (mIsExpanded) {
if (mShowingManage) {
showManageMenu(false);
- } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ } else if (isManageEduVisible()) {
mManageEduView.hide();
} else {
mBubbleData.setExpanded(false);
@@ -2158,7 +2172,7 @@ public class BubbleStackView extends FrameLayout
cancelDelayedExpandCollapseSwitchAnimations();
final boolean showVertically = mPositioner.showBubblesVertically();
mIsExpanded = true;
- if (isStackEduShowing()) {
+ if (isStackEduVisible()) {
mStackEduView.hide(true /* fromExpansion */);
}
beforeExpandedViewAnimation();
@@ -2280,7 +2294,7 @@ public class BubbleStackView extends FrameLayout
private void animateCollapse() {
cancelDelayedExpandCollapseSwitchAnimations();
- if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
+ if (isManageEduVisible()) {
mManageEduView.hide();
}
@@ -2677,7 +2691,7 @@ public class BubbleStackView extends FrameLayout
if (flyoutMessage == null
|| flyoutMessage.message == null
|| !bubble.showFlyout()
- || isStackEduShowing()
+ || isStackEduVisible()
|| isExpanded()
|| mIsExpansionAnimating
|| mIsGestureInProgress
@@ -2800,7 +2814,7 @@ public class BubbleStackView extends FrameLayout
* them.
*/
public void getTouchableRegion(Rect outRect) {
- if (isStackEduShowing()) {
+ if (isStackEduVisible()) {
// When user education shows then capture all touches
outRect.set(0, 0, getWidth(), getHeight());
return;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
index e8f3f69ca64e..de967bfa288b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
@@ -29,6 +29,8 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
@@ -162,4 +164,27 @@ public class BubbleTest extends ShellTestCase {
verify(mBubbleMetadataFlagListener, never()).onBubbleMetadataFlagChanged(any());
}
+
+ @Test
+ public void testBubbleIsConversation_hasConversationShortcut() {
+ Bubble bubble = createBubbleWithShortcut();
+ assertThat(bubble.getShortcutInfo()).isNotNull();
+ assertThat(bubble.isConversation()).isTrue();
+ }
+
+ @Test
+ public void testBubbleIsConversation_hasNoShortcut() {
+ Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor);
+ assertThat(bubble.getShortcutInfo()).isNull();
+ assertThat(bubble.isConversation()).isFalse();
+ }
+
+ private Bubble createBubbleWithShortcut() {
+ ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext)
+ .setId("mockShortcutId")
+ .build();
+ return new Bubble("mockKey", shortcutInfo, 10, Resources.ID_NULL,
+ "mockTitle", 0 /* taskId */, "mockLocus", true /* isDismissible */,
+ mMainExecutor, mBubbleMetadataFlagListener);
+ }
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 3ba1d1f0eca2..c1ee74a70a15 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -75,11 +75,13 @@ public class AudioPolicy {
*/
public static final int POLICY_STATUS_REGISTERED = 2;
+ @GuardedBy("mLock")
private int mStatus;
+ @GuardedBy("mLock")
private String mRegistrationId;
- private AudioPolicyStatusListener mStatusListener;
- private boolean mIsFocusPolicy;
- private boolean mIsTestFocusPolicy;
+ private final AudioPolicyStatusListener mStatusListener;
+ private final boolean mIsFocusPolicy;
+ private final boolean mIsTestFocusPolicy;
/**
* The list of AudioTrack instances created to inject audio into the associated mixes
@@ -115,6 +117,7 @@ public class AudioPolicy {
private Context mContext;
+ @GuardedBy("mLock")
private AudioPolicyConfig mConfig;
private final MediaProjection mProjection;
@@ -552,7 +555,6 @@ public class AudioPolicy {
/** @hide */
public void reset() {
setRegistration(null);
- mConfig.reset();
}
public void setRegistration(String regId) {
@@ -563,6 +565,7 @@ public class AudioPolicy {
mStatus = POLICY_STATUS_REGISTERED;
} else {
mStatus = POLICY_STATUS_UNREGISTERED;
+ mConfig.reset();
}
}
sendMsg(MSG_POLICY_STATUS_CHANGE);
@@ -940,14 +943,9 @@ public class AudioPolicy {
}
private void onPolicyStatusChange() {
- AudioPolicyStatusListener l;
- synchronized (mLock) {
- if (mStatusListener == null) {
- return;
- }
- l = mStatusListener;
+ if (mStatusListener != null) {
+ mStatusListener.onStatusChange();
}
- l.onStatusChange();
}
//==================================================
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index ce9773312a10..7a85d21bf144 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -42,9 +42,7 @@ public class AudioPolicyConfig implements Parcelable {
private String mRegistrationId = null;
- /** counter for the mixes that are / have been in the list of AudioMix
- * e.g. register 4 mixes (counter is 3), remove 1 (counter is 3), add 1 (counter is 4)
- */
+ // Corresponds to id of next mix to be registered.
private int mMixCounter = 0;
protected AudioPolicyConfig(AudioPolicyConfig conf) {
@@ -286,7 +284,7 @@ public class AudioPolicyConfig implements Parcelable {
if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) ==
AudioMix.ROUTE_FLAG_LOOP_BACK) {
mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
- + mMixCounter);
+ + mMixCounter++);
} else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) ==
AudioMix.ROUTE_FLAG_RENDER) {
mix.setRegistration(mix.mDeviceAddress);
@@ -294,7 +292,6 @@ public class AudioPolicyConfig implements Parcelable {
} else {
mix.setRegistration("");
}
- mMixCounter++;
}
@GuardedBy("mMixes")
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/DataServiceUtils.java b/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/DataServiceUtils.java
index 250187f210dc..df0e61833269 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/DataServiceUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/DataServiceUtils.java
@@ -312,12 +312,6 @@ public class DataServiceUtils {
"isFirstRemovableSubscription";
/**
- * The name of the default SIM config column,
- * {@see SubscriptionUtil#getDefaultSimConfig(Context, int)}.
- */
- public static final String COLUMN_DEFAULT_SIM_CONFIG = "defaultSimConfig";
-
- /**
* The name of the default subscription selection column,
* {@see SubscriptionUtil#getSubscriptionOrDefault(Context, int)}.
*/
@@ -349,32 +343,6 @@ public class DataServiceUtils {
public static final String COLUMN_IS_AVAILABLE_SUBSCRIPTION = "isAvailableSubscription";
/**
- * The name of the default voice subscription state column, see
- * {@link SubscriptionManager#getDefaultVoiceSubscriptionId()}.
- */
- public static final String COLUMN_IS_DEFAULT_VOICE_SUBSCRIPTION =
- "isDefaultVoiceSubscription";
-
- /**
- * The name of the default sms subscription state column, see
- * {@link SubscriptionManager#getDefaultSmsSubscriptionId()}.
- */
- public static final String COLUMN_IS_DEFAULT_SMS_SUBSCRIPTION = "isDefaultSmsSubscription";
-
- /**
- * The name of the default data subscription state column, see
- * {@link SubscriptionManager#getDefaultDataSubscriptionId()}.
- */
- public static final String COLUMN_IS_DEFAULT_DATA_SUBSCRIPTION =
- "isDefaultDataSubscription";
-
- /**
- * The name of the default subscription state column, see
- * {@link SubscriptionManager#getDefaultSubscriptionId()}.
- */
- public static final String COLUMN_IS_DEFAULT_SUBSCRIPTION = "isDefaultSubscription";
-
- /**
* The name of the active data subscription state column, see
* {@link SubscriptionManager#getActiveDataSubscriptionId()}.
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/SubscriptionInfoEntity.java b/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/SubscriptionInfoEntity.java
index 23566f760444..c40388fee710 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/SubscriptionInfoEntity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/dataservice/SubscriptionInfoEntity.java
@@ -37,12 +37,10 @@ public class SubscriptionInfoEntity {
String countryIso, boolean isEmbedded, int cardId, int portIndex,
boolean isOpportunistic, @Nullable String groupUUID, int subscriptionType,
String uniqueName, boolean isSubscriptionVisible, String formattedPhoneNumber,
- boolean isFirstRemovableSubscription, String defaultSimConfig,
- boolean isDefaultSubscriptionSelection, boolean isValidSubscription,
- boolean isUsableSubscription, boolean isActiveSubscriptionId,
- boolean isAvailableSubscription, boolean isDefaultVoiceSubscription,
- boolean isDefaultSmsSubscription, boolean isDefaultDataSubscription,
- boolean isDefaultSubscription, boolean isActiveDataSubscriptionId) {
+ boolean isFirstRemovableSubscription, boolean isDefaultSubscriptionSelection,
+ boolean isValidSubscription, boolean isUsableSubscription,
+ boolean isActiveSubscriptionId, boolean isAvailableSubscription,
+ boolean isActiveDataSubscriptionId) {
this.subId = subId;
this.simSlotIndex = simSlotIndex;
this.carrierId = carrierId;
@@ -62,16 +60,11 @@ public class SubscriptionInfoEntity {
this.isSubscriptionVisible = isSubscriptionVisible;
this.formattedPhoneNumber = formattedPhoneNumber;
this.isFirstRemovableSubscription = isFirstRemovableSubscription;
- this.defaultSimConfig = defaultSimConfig;
this.isDefaultSubscriptionSelection = isDefaultSubscriptionSelection;
this.isValidSubscription = isValidSubscription;
this.isUsableSubscription = isUsableSubscription;
this.isActiveSubscriptionId = isActiveSubscriptionId;
this.isAvailableSubscription = isAvailableSubscription;
- this.isDefaultVoiceSubscription = isDefaultVoiceSubscription;
- this.isDefaultSmsSubscription = isDefaultSmsSubscription;
- this.isDefaultDataSubscription = isDefaultDataSubscription;
- this.isDefaultSubscription = isDefaultSubscription;
this.isActiveDataSubscriptionId = isActiveDataSubscriptionId;
}
@@ -135,9 +128,6 @@ public class SubscriptionInfoEntity {
@ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_FIRST_REMOVABLE_SUBSCRIPTION)
public boolean isFirstRemovableSubscription;
- @ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_DEFAULT_SIM_CONFIG)
- public String defaultSimConfig;
-
@ColumnInfo(name =
DataServiceUtils.SubscriptionInfoData.COLUMN_IS_DEFAULT_SUBSCRIPTION_SELECTION)
public boolean isDefaultSubscriptionSelection;
@@ -154,18 +144,6 @@ public class SubscriptionInfoEntity {
@ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_AVAILABLE_SUBSCRIPTION)
public boolean isAvailableSubscription;
- @ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_DEFAULT_VOICE_SUBSCRIPTION)
- public boolean isDefaultVoiceSubscription;
-
- @ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_DEFAULT_SMS_SUBSCRIPTION)
- public boolean isDefaultSmsSubscription;
-
- @ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_DEFAULT_DATA_SUBSCRIPTION)
- public boolean isDefaultDataSubscription;
-
- @ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_DEFAULT_SUBSCRIPTION)
- public boolean isDefaultSubscription;
-
@ColumnInfo(name = DataServiceUtils.SubscriptionInfoData.COLUMN_IS_ACTIVE_DATA_SUBSCRIPTION)
public boolean isActiveDataSubscriptionId;
@@ -207,16 +185,11 @@ public class SubscriptionInfoEntity {
result = 31 * result + Boolean.hashCode(isSubscriptionVisible);
result = 31 * result + formattedPhoneNumber.hashCode();
result = 31 * result + Boolean.hashCode(isFirstRemovableSubscription);
- result = 31 * result + defaultSimConfig.hashCode();
result = 31 * result + Boolean.hashCode(isDefaultSubscriptionSelection);
result = 31 * result + Boolean.hashCode(isValidSubscription);
result = 31 * result + Boolean.hashCode(isUsableSubscription);
result = 31 * result + Boolean.hashCode(isActiveSubscriptionId);
result = 31 * result + Boolean.hashCode(isAvailableSubscription);
- result = 31 * result + Boolean.hashCode(isDefaultVoiceSubscription);
- result = 31 * result + Boolean.hashCode(isDefaultSmsSubscription);
- result = 31 * result + Boolean.hashCode(isDefaultDataSubscription);
- result = 31 * result + Boolean.hashCode(isDefaultSubscription);
result = 31 * result + Boolean.hashCode(isActiveDataSubscriptionId);
return result;
}
@@ -250,16 +223,11 @@ public class SubscriptionInfoEntity {
&& isSubscriptionVisible == info.isSubscriptionVisible
&& TextUtils.equals(formattedPhoneNumber, info.formattedPhoneNumber)
&& isFirstRemovableSubscription == info.isFirstRemovableSubscription
- && TextUtils.equals(defaultSimConfig, info.defaultSimConfig)
&& isDefaultSubscriptionSelection == info.isDefaultSubscriptionSelection
&& isValidSubscription == info.isValidSubscription
&& isUsableSubscription == info.isUsableSubscription
&& isActiveSubscriptionId == info.isActiveSubscriptionId
&& isAvailableSubscription == info.isAvailableSubscription
- && isDefaultVoiceSubscription == info.isDefaultVoiceSubscription
- && isDefaultSmsSubscription == info.isDefaultSmsSubscription
- && isDefaultDataSubscription == info.isDefaultDataSubscription
- && isDefaultSubscription == info.isDefaultSubscription
&& isActiveDataSubscriptionId == info.isActiveDataSubscriptionId;
}
@@ -303,8 +271,6 @@ public class SubscriptionInfoEntity {
.append(formattedPhoneNumber)
.append(", isFirstRemovableSubscription = ")
.append(isFirstRemovableSubscription)
- .append(", defaultSimConfig = ")
- .append(defaultSimConfig)
.append(", isDefaultSubscriptionSelection = ")
.append(isDefaultSubscriptionSelection)
.append(", isValidSubscription = ")
@@ -315,14 +281,6 @@ public class SubscriptionInfoEntity {
.append(isActiveSubscriptionId)
.append(", isAvailableSubscription = ")
.append(isAvailableSubscription)
- .append(", isDefaultVoiceSubscription = ")
- .append(isDefaultVoiceSubscription)
- .append(", isDefaultSmsSubscription = ")
- .append(isDefaultSmsSubscription)
- .append(", isDefaultDataSubscription = ")
- .append(isDefaultDataSubscription)
- .append(", isDefaultSubscription = ")
- .append(isDefaultSubscription)
.append(", isActiveDataSubscriptionId = ")
.append(isActiveDataSubscriptionId)
.append(")}");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index e736253dc90f..5a8c59489ec8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2311,7 +2311,7 @@ public class SettingsProvider extends ContentProvider {
@NonNull Set<String> flags) {
boolean hasAllowlistPermission =
context.checkCallingOrSelfPermission(
- Manifest.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG)
+ Manifest.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG)
== PackageManager.PERMISSION_GRANTED;
boolean hasWritePermission =
context.checkCallingOrSelfPermission(
@@ -2331,7 +2331,7 @@ public class SettingsProvider extends ContentProvider {
}
} else {
throw new SecurityException("Permission denial to mutate flag, must have root, "
- + "WRITE_DEVICE_CONFIG, or ALLOWLISTED_WRITE_DEVICE_CONFIG");
+ + "WRITE_DEVICE_CONFIG, or WRITE_ALLOWLISTED_DEVICE_CONFIG");
}
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index f2f0fe987f36..19f1a86ec90c 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -273,7 +273,6 @@ public class SettingsBackupTest {
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
- Settings.Global.STYLUS_HANDWRITING_ENABLED,
Settings.Global.STYLUS_EVER_USED,
Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT,
Settings.Global.ENABLE_MULTI_SLOT_TIMEOUT_MILLIS,
@@ -785,6 +784,7 @@ public class SettingsBackupTest {
Settings.Secure.SMS_DEFAULT_APPLICATION,
Settings.Secure.SPELL_CHECKER_ENABLED, // Intentionally removed in Q
Settings.Secure.STYLUS_BUTTONS_ENABLED,
+ Settings.Secure.STYLUS_HANDWRITING_ENABLED,
Settings.Secure.TRUST_AGENTS_INITIALIZED,
Settings.Secure.KNOWN_TRUST_AGENTS_INITIALIZED,
Settings.Secure.TV_APP_USES_NON_SYSTEM_INPUTS,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 4c48f0e63b16..fedfb43535cc 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -148,7 +148,7 @@
<uses-permission android:name="android.permission.LOCATION_BYPASS" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
- <uses-permission android:name="android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG" />
<uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index 8d4431520c75..befbfab7dbc3 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -37,4 +37,12 @@
<dimen name="percent_displacement_at_fade_out" format="float">0.1066</dimen>
<integer name="qs_carrier_max_em">7</integer>
+
+ <!-- Maximum number of notification icons shown on the Always on Display
+ (excluding overflow dot) -->
+ <integer name="max_notif_icons_on_aod">3</integer>
+ <!-- Maximum number of notification icons shown on the lockscreen (excluding overflow dot) -->
+ <integer name="max_notif_icons_on_lockscreen">3</integer>
+ <!-- Maximum number of notification icons shown in the status bar (excluding overflow dot) -->
+ <integer name="max_notif_static_icons">4</integer>
</resources> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 7ffb59422bc4..79a51d6670c4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -701,6 +701,6 @@ object Flags {
// TODO(b/272805037): Tracking Bug
@JvmField
- val ADVANCED_VPN_ENABLED = releasedFlag(2800, name = "AdvancedVpn__enable_feature",
- namespace = "vpn")
+ val ADVANCED_VPN_ENABLED = unreleasedFlag(2800, name = "AdvancedVpn__enable_feature",
+ namespace = "vpn", teamfood = true)
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 2d7861be2da9..f5c0a94d07f2 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -174,21 +174,26 @@ constructor(
infoReference.set(info)
- // TODO(b/266686199): We should handle when app not available. For now, we log.
- val intent = createNoteTaskIntent(info)
try {
+ // TODO(b/266686199): We should handle when app not available. For now, we log.
logDebug { "onShowNoteTask - start: $info on user#${user.identifier}" }
when (info.launchMode) {
is NoteTaskLaunchMode.AppBubble -> {
// TODO: provide app bubble icon
+ val intent = createNoteTaskIntent(info)
bubbles.showOrHideAppBubble(intent, user, null /* icon */)
// App bubble logging happens on `onBubbleExpandChanged`.
logDebug { "onShowNoteTask - opened as app bubble: $info" }
}
is NoteTaskLaunchMode.Activity -> {
if (activityManager.isInForeground(info.packageName)) {
- logDebug { "onShowNoteTask - already opened as activity: $info" }
+ // Force note task into background by calling home.
+ val intent = createHomeIntent()
+ context.startActivityAsUser(intent, user)
+ eventLogger.logNoteTaskClosed(info)
+ logDebug { "onShowNoteTask - closed as activity: $info" }
} else {
+ val intent = createNoteTaskIntent(info)
context.startActivityAsUser(intent, user)
eventLogger.logNoteTaskOpened(info)
logDebug { "onShowNoteTask - opened as activity: $info" }
@@ -199,7 +204,7 @@ constructor(
} catch (e: ActivityNotFoundException) {
logDebug { "onShowNoteTask - failed: $info" }
}
- logDebug { "onShowNoteTask - compoleted: $info" }
+ logDebug { "onShowNoteTask - completed: $info" }
}
/**
@@ -306,3 +311,10 @@ private fun createNoteTaskIntent(info: NoteTaskInfo): Intent =
private inline fun Any.logDebug(message: () -> String) {
if (Build.IS_DEBUGGABLE) Log.d(this::class.java.simpleName.orEmpty(), message())
}
+
+/** Creates an [Intent] which forces the current app to background by calling home. */
+private fun createHomeIntent(): Intent =
+ Intent(Intent.ACTION_MAIN).apply {
+ addCategory(Intent.CATEGORY_HOME)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 0b2ae05b7c9b..72286f175671 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -161,6 +161,10 @@ open class UserTrackerImpl internal constructor(
private fun registerUserSwitchObserver() {
iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() {
+ override fun onBeforeUserSwitching(newUserId: Int) {
+ setUserIdInternal(newUserId)
+ }
+
override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
backgroundHandler.run {
handleUserSwitching(newUserId)
@@ -181,8 +185,6 @@ open class UserTrackerImpl internal constructor(
Assert.isNotMainThread()
Log.i(TAG, "Switching to user $newUserId")
- setUserIdInternal(newUserId)
-
val list = synchronized(callbacks) {
callbacks.toList()
}
@@ -205,7 +207,6 @@ open class UserTrackerImpl internal constructor(
Assert.isNotMainThread()
Log.i(TAG, "Switched to user $newUserId")
- setUserIdInternal(newUserId)
notifySubscribers {
onUserChanged(newUserId, userContext)
onProfilesChanged(userProfiles)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 4ee2de11abdf..006a029de8e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -136,11 +136,13 @@ public class NotificationIconContainer extends ViewGroup {
}
}.setDuration(CONTENT_FADE_DURATION);
- private static final int MAX_ICONS_ON_AOD = 3;
+ /* Maximum number of icons on AOD when also showing overflow dot. */
+ private int mMaxIconsOnAod;
/* Maximum number of icons in short shelf on lockscreen when also showing overflow dot. */
- public static final int MAX_ICONS_ON_LOCKSCREEN = 3;
- public static final int MAX_STATIC_ICONS = 4;
+ private int mMaxIconsOnLockscreen;
+ /* Maximum number of icons in the status bar when also showing overflow dot. */
+ private int mMaxStaticIcons;
private boolean mIsStaticLayout = true;
private final HashMap<View, IconState> mIconStates = new HashMap<>();
@@ -174,14 +176,19 @@ public class NotificationIconContainer extends ViewGroup {
public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
- initDimens();
+ initResources();
setWillNotDraw(!(DEBUG || DEBUG_OVERFLOW));
}
- private void initDimens() {
+ private void initResources() {
+ mMaxIconsOnAod = getResources().getInteger(R.integer.max_notif_icons_on_aod);
+ mMaxIconsOnLockscreen = getResources().getInteger(R.integer.max_notif_icons_on_lockscreen);
+ mMaxStaticIcons = getResources().getInteger(R.integer.max_notif_static_icons);
+
mDotPadding = getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding);
mStaticDotRadius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);
mStaticDotDiameter = 2 * mStaticDotRadius;
+
final Context themedContext = new ContextThemeWrapper(getContext(),
com.android.internal.R.style.Theme_DeviceDefault_DayNight);
mThemedTextColorPrimary = Utils.getColorAttr(themedContext,
@@ -225,7 +232,7 @@ public class NotificationIconContainer extends ViewGroup {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- initDimens();
+ initResources();
}
@Override
@@ -424,7 +431,7 @@ public class NotificationIconContainer extends ViewGroup {
return 0f;
}
final float contentWidth =
- mIconSize * MathUtils.min(numIcons, MAX_ICONS_ON_LOCKSCREEN + 1);
+ mIconSize * MathUtils.min(numIcons, mMaxIconsOnLockscreen + 1);
return getActualPaddingStart()
+ contentWidth
+ getActualPaddingEnd();
@@ -539,8 +546,8 @@ public class NotificationIconContainer extends ViewGroup {
}
private int getMaxVisibleIcons(int childCount) {
- return mOnLockScreen ? MAX_ICONS_ON_AOD :
- mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
+ return mOnLockScreen ? mMaxIconsOnAod :
+ mIsStaticLayout ? mMaxStaticIcons : childCount;
}
private float getLayoutEnd() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 53e08ea8e10d..118bfc55dd4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -14,6 +14,7 @@ import android.view.WindowManager.fixScale
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
+import com.android.systemui.DejankUtils
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.KeyguardViewMediator
@@ -27,6 +28,7 @@ import com.android.systemui.statusbar.notification.PropertyAnimator
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.TraceUtils
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
@@ -116,6 +118,11 @@ class UnlockedScreenOffAnimationController @Inject constructor(
})
}
+ // FrameCallback used to delay starting the light reveal animation until the next frame
+ private val startLightRevealCallback = TraceUtils.namedRunnable("startLightReveal") {
+ lightRevealAnimator.start()
+ }
+
val animatorDurationScaleObserver = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
updateAnimatorDurationScale()
@@ -223,6 +230,7 @@ class UnlockedScreenOffAnimationController @Inject constructor(
decidedToAnimateGoingToSleep = null
shouldAnimateInKeyguard = false
+ DejankUtils.removeCallbacks(startLightRevealCallback)
lightRevealAnimator.cancel()
handler.removeCallbacksAndMessages(null)
}
@@ -253,7 +261,14 @@ class UnlockedScreenOffAnimationController @Inject constructor(
shouldAnimateInKeyguard = true
lightRevealAnimationPlaying = true
- lightRevealAnimator.start()
+
+ // Start the animation on the next frame. startAnimation() is called after
+ // PhoneWindowManager makes a binder call to System UI on
+ // IKeyguardService#onStartedGoingToSleep(). By the time we get here, system_server is
+ // already busy making changes to PowerManager and DisplayManager. This increases our
+ // chance of missing the first frame, so to mitigate this we should start the animation
+ // on the next frame.
+ DejankUtils.postAfterTraversal(startLightRevealCallback)
handler.postDelayed({
// Only run this callback if the device is sleeping (not interactive). This callback
// is removed in onStartedWakingUp, but since that event is asynchronously
diff --git a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
index b311318fb111..64234c205617 100644
--- a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
@@ -17,6 +17,7 @@
package com.android.systemui.util
import android.os.Trace
+import android.os.TraceNameSupplier
/**
* Run a block within a [Trace] section.
@@ -39,5 +40,16 @@ class TraceUtils {
inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable {
return Runnable { traceSection(tag) { block() } }
}
+
+ /**
+ * Helper function for creating a Runnable object that implements TraceNameSupplier.
+ * This is useful for posting Runnables to Handlers with meaningful names.
+ */
+ inline fun namedRunnable(tag: String, crossinline block: () -> Unit): Runnable {
+ return object : Runnable, TraceNameSupplier {
+ override fun getTraceName(): String = tag
+ override fun run() = block()
+ }
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 9897ce106137..fbe089a0616f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -25,6 +25,8 @@ import android.app.role.RoleManager.ROLE_NOTES
import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.content.Intent.ACTION_MAIN
+import android.content.Intent.CATEGORY_HOME
import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
@@ -278,7 +280,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
}
@Test
- fun showNoteTask_keyguardIsLocked_noteIsOpen_shouldStartActivityAndLogUiEvent() {
+ fun showNoteTask_keyguardIsLocked_noteIsOpen_shouldCloseActivityAndLogUiEvent() {
val expectedInfo =
NOTE_TASK_INFO.copy(
entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
@@ -291,8 +293,17 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
- verify(context, never()).startActivityAsUser(any(), any())
- verifyZeroInteractions(bubbles, eventLogger)
+ val intentCaptor = argumentCaptor<Intent>()
+ val userCaptor = argumentCaptor<UserHandle>()
+ verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(ACTION_MAIN)
+ assertThat(intent.categories).contains(CATEGORY_HOME)
+ assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
+ }
+ assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
+ verify(eventLogger).logNoteTaskClosed(expectedInfo)
+ verifyZeroInteractions(bubbles)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index 71ba21538a8e..aa98f08e9015 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -167,6 +167,7 @@ class UserTrackerImplTest : SysuiTestCase() {
val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onBeforeUserSwitching(newID)
captor.value.onUserSwitching(newID, userSwitchingReply)
verify(userSwitchingReply).sendResult(any())
@@ -290,6 +291,7 @@ class UserTrackerImplTest : SysuiTestCase() {
val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onBeforeUserSwitching(newID)
captor.value.onUserSwitching(newID, userSwitchingReply)
verify(userSwitchingReply).sendResult(any())
@@ -308,6 +310,7 @@ class UserTrackerImplTest : SysuiTestCase() {
val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onBeforeUserSwitching(newID)
captor.value.onUserSwitchComplete(newID)
assertThat(callback.calledOnUserChanged).isEqualTo(1)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index cc3b4ab0fb4e..652052736bed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -57,6 +57,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
import android.content.pm.UserInfo;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -100,6 +101,7 @@ import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeWindowLogger;
import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.statusbar.NotificationEntryHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -135,6 +137,7 @@ import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.bubbles.StackEducationViewKt;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
@@ -1669,6 +1672,60 @@ public class BubblesTest extends SysuiTestCase {
}
@Test
+ public void testShowStackEdu_isNotConversationBubble() {
+ // Setup
+ setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, false);
+ BubbleEntry bubbleEntry = createBubbleEntry(false /* isConversation */);
+ mBubbleController.updateBubble(bubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ // Click on bubble
+ Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
+ assertFalse(bubble.isConversation());
+ bubble.getIconView().callOnClick();
+
+ // Check education is not shown
+ BubbleStackView stackView = mBubbleController.getStackView();
+ assertFalse(stackView.isStackEduVisible());
+ }
+
+ @Test
+ public void testShowStackEdu_isConversationBubble() {
+ // Setup
+ setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, false);
+ BubbleEntry bubbleEntry = createBubbleEntry(true /* isConversation */);
+ mBubbleController.updateBubble(bubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ // Click on bubble
+ Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
+ assertTrue(bubble.isConversation());
+ bubble.getIconView().callOnClick();
+
+ // Check education is shown
+ BubbleStackView stackView = mBubbleController.getStackView();
+ assertTrue(stackView.isStackEduVisible());
+ }
+
+ @Test
+ public void testShowStackEdu_isSeenConversationBubble() {
+ // Setup
+ setPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION, true);
+ BubbleEntry bubbleEntry = createBubbleEntry(true /* isConversation */);
+ mBubbleController.updateBubble(bubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ // Click on bubble
+ Bubble bubble = mBubbleData.getBubbleInStackWithKey(bubbleEntry.getKey());
+ assertTrue(bubble.isConversation());
+ bubble.getIconView().callOnClick();
+
+ // Check education is not shown
+ BubbleStackView stackView = mBubbleController.getStackView();
+ assertFalse(stackView.isStackEduVisible());
+ }
+
+ @Test
public void testShowOrHideAppBubble_addsAndExpand() {
assertThat(mBubbleController.isStackExpanded()).isFalse();
assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
@@ -1816,6 +1873,20 @@ public class BubblesTest extends SysuiTestCase {
mock(Bubbles.PendingIntentCanceledListener.class), new SyncExecutor());
}
+ private BubbleEntry createBubbleEntry(boolean isConversation) {
+ NotificationEntry notificationEntry = mNotificationTestHelper.createBubble(mDeleteIntent);
+ if (isConversation) {
+ ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext)
+ .setId("shortcutId")
+ .build();
+ NotificationEntryHelper.modifyRanking(notificationEntry)
+ .setIsConversation(true)
+ .setShortcutInfo(shortcutInfo)
+ .build();
+ }
+ return mBubblesManager.notifToBubbleEntry(notificationEntry);
+ }
+
/** Creates a context that will return a PackageManager with specific AppInfo. */
private Context setUpContextWithPackageManager(String pkg, ApplicationInfo info)
throws Exception {
@@ -1852,6 +1923,15 @@ public class BubblesTest extends SysuiTestCase {
bubbleMetadata.setFlags(flags);
}
+ /**
+ * Set preferences boolean value for key
+ * Used to setup global state for stack view education tests
+ */
+ private void setPrefBoolean(String key, boolean enabled) {
+ mContext.getSharedPreferences(mContext.getPackageName(), Context.MODE_PRIVATE)
+ .edit().putBoolean(key, enabled).apply();
+ }
+
private Notification.BubbleMetadata getMetadata() {
Intent target = new Intent(mContext, BubblesTestActivity.class);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, FLAG_MUTABLE);
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 990dd64434a0..484e9566b036 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -338,9 +338,7 @@ class InputController {
}
synchronized (mLock) {
- InputDeviceDescriptor[] values = mInputDeviceDescriptors.values().toArray(
- new InputDeviceDescriptor[0]);
- for (InputDeviceDescriptor value : values) {
+ for (InputDeviceDescriptor value : mInputDeviceDescriptors.values()) {
if (value.mName.equals(deviceName)) {
throw new DeviceCreationException(
"Input device name already in use: " + deviceName);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 713b993824f9..8d8ed196be18 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -38,6 +38,8 @@ import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.StopUserOnSwitch;
+import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
+import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityManagerInternal.MEDIA_PROJECTION_TOKEN_EVENT_CREATED;
@@ -7500,9 +7502,9 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void registerUidFrozenStateChangedCallback(
@NonNull IUidFrozenStateChangedCallback callback) {
+ Preconditions.checkNotNull(callback, "callback cannot be null");
enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
"registerUidFrozenStateChangedCallback()");
- Preconditions.checkNotNull(callback, "callback cannot be null");
synchronized (mUidFrozenStateChangedCallbackList) {
final boolean registered = mUidFrozenStateChangedCallbackList.register(callback);
if (!registered) {
@@ -7520,15 +7522,48 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void unregisterUidFrozenStateChangedCallback(
@NonNull IUidFrozenStateChangedCallback callback) {
+ Preconditions.checkNotNull(callback, "callback cannot be null");
enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
"unregisterUidFrozenStateChangedCallback()");
- Preconditions.checkNotNull(callback, "callback cannot be null");
synchronized (mUidFrozenStateChangedCallbackList) {
mUidFrozenStateChangedCallbackList.unregister(callback);
}
}
/**
+ * Query the frozen state of a list of UIDs.
+ *
+ * @param uids the array of UIDs which the client would like to know the frozen state of.
+ * @return An array containing the frozen state for each requested UID, by index. Will be set
+ * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN}
+ * if the UID is frozen. If the UID is not frozen or not found,
+ * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN}
+ * will be set.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ @Override
+ public @NonNull int[] getUidFrozenState(@NonNull int[] uids) {
+ Preconditions.checkNotNull(uids, "uid array cannot be null");
+ enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+ "getUidFrozenState()");
+
+ final int[] frozenStates = new int[uids.length];
+ synchronized (mProcLock) {
+ for (int i = 0; i < uids.length; i++) {
+ final UidRecord uidRec = mProcessList.mActiveUids.get(uids[i]);
+ if (uidRec != null && uidRec.areAllProcessesFrozen()) {
+ frozenStates[i] = UID_FROZEN_STATE_FROZEN;
+ } else {
+ frozenStates[i] = UID_FROZEN_STATE_UNFROZEN;
+ }
+ }
+ }
+ return frozenStates;
+ }
+
+ /**
* Notify the system that a UID has been frozen or unfrozen.
*
* @param uids The Uid(s) in question
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 1b378837e558..d926c2c7c7a8 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2141,6 +2141,17 @@ class UserController implements Handler.Callback {
final int observerCount = mUserSwitchObservers.beginBroadcast();
if (observerCount > 0) {
+ for (int i = 0; i < observerCount; i++) {
+ final String name = "#" + i + " " + mUserSwitchObservers.getBroadcastCookie(i);
+ t.traceBegin("onBeforeUserSwitching-" + name);
+ try {
+ mUserSwitchObservers.getBroadcastItem(i).onBeforeUserSwitching(newUserId);
+ } catch (RemoteException e) {
+ // Ignore
+ } finally {
+ t.traceEnd();
+ }
+ }
final ArraySet<String> curWaitingUserSwitchCallbacks = new ArraySet<>();
synchronized (mLock) {
uss.switching = true;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7a0bf0cacdfb..b440208e3e32 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -20,6 +20,8 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.Settings.Secure.STYLUS_HANDWRITING_DEFAULT_VALUE;
+import static android.provider.Settings.Secure.STYLUS_HANDWRITING_ENABLED;
import static android.server.inputmethod.InputMethodManagerServiceProto.BACK_DISPOSITION;
import static android.server.inputmethod.InputMethodManagerServiceProto.BOUND_TO_METHOD;
import static android.server.inputmethod.InputMethodManagerServiceProto.CUR_ATTRIBUTE;
@@ -2067,10 +2069,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
synchronized (ImfLock.class) {
+ if (!isStylusHandwritingEnabled(mContext, userId)) {
+ return false;
+ }
+
+ // Check if selected IME of current user supports handwriting.
if (userId == mSettings.getCurrentUserId()) {
return mBindingController.supportsStylusHandwriting();
}
-
//TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList.
//TODO(b/210039666): use cache.
final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId);
@@ -2081,6 +2087,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
+ private boolean isStylusHandwritingEnabled(
+ @NonNull Context context, @UserIdInt int userId) {
+ // If user is a profile, use preference of it`s parent profile.
+ final int profileParentUserId = mUserManagerInternal.getProfileParentId(userId);
+ if (Settings.Secure.getIntForUser(context.getContentResolver(),
+ STYLUS_HANDWRITING_ENABLED, STYLUS_HANDWRITING_DEFAULT_VALUE,
+ profileParentUserId) == 0) {
+ return false;
+ }
+ return true;
+ }
+
@GuardedBy("ImfLock.class")
private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId,
@DirectBootAwareness int directBootAwareness, int callingUid) {
@@ -3418,8 +3436,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void prepareStylusHandwritingDelegation(
@NonNull IInputMethodClient client,
+ @UserIdInt int userId,
@NonNull String delegatePackageName,
@NonNull String delegatorPackageName) {
+ if (!isStylusHandwritingEnabled(mContext, userId)) {
+ Slog.w(TAG, "Can not prepare stylus handwriting delegation. Stylus handwriting"
+ + " pref is disabled for user: " + userId);
+ return;
+ }
if (!verifyClientAndPackageMatch(client, delegatorPackageName)) {
Slog.w(TAG, "prepareStylusHandwritingDelegation() fail");
throw new IllegalArgumentException("Delegator doesn't match Uid");
@@ -3430,8 +3454,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public boolean acceptStylusHandwritingDelegation(
@NonNull IInputMethodClient client,
+ @UserIdInt int userId,
@NonNull String delegatePackageName,
@NonNull String delegatorPackageName) {
+ if (!isStylusHandwritingEnabled(mContext, userId)) {
+ Slog.w(TAG, "Can not accept stylus handwriting delegation. Stylus handwriting"
+ + " pref is disabled for user: " + userId);
+ return false;
+ }
if (!verifyDelegator(client, delegatePackageName, delegatorPackageName)) {
return false;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a4eb417be4e1..65dcec702ef4 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3323,7 +3323,8 @@ public class NotificationManagerService extends SystemService {
final boolean isSystemToast = isCallerSystemOrPhone()
|| PackageManagerService.PLATFORM_PACKAGE_NAME.equals(pkg);
boolean isAppRenderedToast = (callback != null);
- if (!checkCanEnqueueToast(pkg, callingUid, isAppRenderedToast, isSystemToast)) {
+ if (!checkCanEnqueueToast(pkg, callingUid, displayId, isAppRenderedToast,
+ isSystemToast)) {
return;
}
@@ -3393,7 +3394,7 @@ public class NotificationManagerService extends SystemService {
}
}
- private boolean checkCanEnqueueToast(String pkg, int callingUid,
+ private boolean checkCanEnqueueToast(String pkg, int callingUid, int displayId,
boolean isAppRenderedToast, boolean isSystemToast) {
final boolean isPackageSuspended = isPackagePaused(pkg);
final boolean notificationsDisabledForPackage = !areNotificationsEnabledForPackage(pkg,
@@ -3423,6 +3424,13 @@ public class NotificationManagerService extends SystemService {
return false;
}
+ int userId = UserHandle.getUserId(callingUid);
+ if (!isSystemToast && !mUmInternal.isUserVisible(userId, displayId)) {
+ Slog.e(TAG, "Suppressing toast from package " + pkg + "/" + callingUid + " as user "
+ + userId + " is not visible on display " + displayId);
+ return false;
+ }
+
return true;
}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index acd4a96c2817..6f7ce80e42b1 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -571,6 +571,7 @@ public class ComputerEngine implements Computer {
if (!blockInstantResolution && !blockNormalResolution) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
+ ri.userHandle = UserHandle.of(userId);
list = new ArrayList<>(1);
list.add(ri);
PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
diff --git a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
index f653e4b26438..6cb6dc07f8b8 100644
--- a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
+++ b/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
@@ -28,7 +28,8 @@ public final class ProcfsMemoryUtil {
"VmHWM:",
"VmRSS:",
"RssAnon:",
- "VmSwap:"
+ "RssShmem:",
+ "VmSwap:",
};
private static final String[] VMSTAT_KEYS = new String[] {
"oom_kill"
@@ -38,7 +39,7 @@ public final class ProcfsMemoryUtil {
/**
* Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS,
- * VmSwap fields in /proc/pid/status in kilobytes or null if not available.
+ * VmSwap, RssShmem fields in /proc/pid/status in kilobytes or null if not available.
*/
@Nullable
public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
@@ -46,8 +47,9 @@ public final class ProcfsMemoryUtil {
output[0] = -1;
output[3] = -1;
output[4] = -1;
+ output[5] = -1;
Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
- if (output[0] == -1 || output[3] == -1 || output[4] == -1) {
+ if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) {
// Could not open or parse file.
return null;
}
@@ -56,7 +58,8 @@ public final class ProcfsMemoryUtil {
snapshot.rssHighWaterMarkInKilobytes = (int) output[1];
snapshot.rssInKilobytes = (int) output[2];
snapshot.anonRssInKilobytes = (int) output[3];
- snapshot.swapInKilobytes = (int) output[4];
+ snapshot.rssShmemKilobytes = (int) output[4];
+ snapshot.swapInKilobytes = (int) output[5];
return snapshot;
}
@@ -101,6 +104,7 @@ public final class ProcfsMemoryUtil {
public int rssInKilobytes;
public int anonRssInKilobytes;
public int swapInKilobytes;
+ public int rssShmemKilobytes;
}
/** Reads and parses selected entries of /proc/vmstat. */
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index f8a4b04180c3..b2f48d9e3d8c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -2290,7 +2290,8 @@ public class StatsPullAtomService extends SystemService {
managedProcess.processName, managedProcess.pid, managedProcess.oomScore,
snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
- gpuMemPerPid.get(managedProcess.pid), managedProcess.hasForegroundServices));
+ gpuMemPerPid.get(managedProcess.pid), managedProcess.hasForegroundServices,
+ snapshot.rssShmemKilobytes));
}
// Complement the data with native system processes. Given these measurements can be taken
// in response to LMKs happening, we want to first collect the managed app stats (to
@@ -2309,7 +2310,8 @@ public class StatsPullAtomService extends SystemService {
-1001 /*Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1.*/,
snapshot.rssInKilobytes, snapshot.anonRssInKilobytes, snapshot.swapInKilobytes,
snapshot.anonRssInKilobytes + snapshot.swapInKilobytes,
- gpuMemPerPid.get(pid), false /* has_foreground_services */));
+ gpuMemPerPid.get(pid), false /* has_foreground_services */,
+ snapshot.rssShmemKilobytes));
}
return StatsManager.PULL_SUCCESS;
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 95fd82ff1154..80d1e1683de1 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -398,6 +398,7 @@ class ActivityMetricsLogger {
/** Returns {@code true} if the incoming activity can belong to this transition. */
boolean canCoalesce(ActivityRecord r) {
return mLastLaunchedActivity.mDisplayContent == r.mDisplayContent
+ && mLastLaunchedActivity.getTask().getBounds().equals(r.getTask().getBounds())
&& mLastLaunchedActivity.getWindowingMode() == r.getWindowingMode();
}
@@ -646,7 +647,7 @@ class ActivityMetricsLogger {
void notifyActivityLaunched(@NonNull LaunchingState launchingState, int resultCode,
boolean newActivityCreated, @Nullable ActivityRecord launchedActivity,
@Nullable ActivityOptions options) {
- if (launchedActivity == null) {
+ if (launchedActivity == null || launchedActivity.getTask() == null) {
// The launch is aborted, e.g. intent not resolved, class not found.
abort(launchingState, "nothing launched");
return;
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index f8fb76acf81e..7c1e9071b926 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -574,7 +574,9 @@ public class ActivityStartController {
mService.deferWindowLayout();
try {
final TransitionController controller = r.mTransitionController;
- if (controller.getTransitionPlayer() != null) {
+ final Transition transition = controller.getCollectingTransition();
+ if (transition != null) {
+ transition.setRemoteAnimationApp(r.app.getThread());
controller.collect(task);
controller.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask));
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 7b9cc6fee602..bbdaa24a694c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2011,6 +2011,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
+ if (r == mRootWindowContainer.getTopResumedActivity()) {
+ setLastResumedActivityUncheckLocked(r, "setFocusedTask-alreadyTop");
+ return;
+ }
final Transition transition = (getTransitionController().isCollecting()
|| !getTransitionController().isShellTransitionsEnabled()) ? null
: getTransitionController().createTransition(TRANSIT_TO_FRONT);
@@ -4788,11 +4792,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// until we've committed to the gesture. The focus will be transferred at the end of
// the transition (if the transient launch is committed) or early if explicitly requested
// via `setFocused*`.
+ boolean focusedAppChanged = false;
if (!getTransitionController().isTransientCollect(r)) {
- final Task prevFocusTask = r.mDisplayContent.mFocusedApp != null
- ? r.mDisplayContent.mFocusedApp.getTask() : null;
- final boolean changed = r.mDisplayContent.setFocusedApp(r);
- if (changed) {
+ focusedAppChanged = r.mDisplayContent.setFocusedApp(r);
+ if (focusedAppChanged) {
mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
true /*updateInputWindows*/);
}
@@ -4801,13 +4804,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mTaskSupervisor.mRecentTasks.add(task);
}
- applyUpdateLockStateLocked(r);
- applyUpdateVrModeLocked(r);
+ if (focusedAppChanged) {
+ applyUpdateLockStateLocked(r);
+ }
+ if (mVrController.mVrService != null) {
+ applyUpdateVrModeLocked(r);
+ }
- EventLogTags.writeWmSetResumedActivity(
- r == null ? -1 : r.mUserId,
- r == null ? "NULL" : r.shortComponentName,
- reason);
+ EventLogTags.writeWmSetResumedActivity(r.mUserId, r.shortComponentName, reason);
}
final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1604c2a0343b..a44f25ca8051 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3300,7 +3300,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// Unlink death from remote to clear the reference from binder -> mRemoteInsetsDeath
// -> this DisplayContent.
setRemoteInsetsController(null);
- mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mOverlayLayer.release();
mA11yOverlayLayer.release();
mWindowingLayer.release();
@@ -5312,8 +5311,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// {@link DisplayContent} ready for use.
mDisplayReady = true;
- mWmService.mAnimator.addDisplayLocked(mDisplayId);
-
if (mWmService.mDisplayManagerInternal != null) {
mWmService.mDisplayManagerInternal
.setDisplayInfoOverrideFromWindowManager(mDisplayId, getDisplayInfo());
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 8fa7592e6da0..951a71d2ddb9 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -66,6 +66,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.IApplicationThread;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
@@ -83,7 +84,6 @@ import android.util.SparseArray;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.WindowManager;
-import android.window.RemoteTransition;
import android.window.ScreenCapture;
import android.window.TransitionInfo;
@@ -160,7 +160,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
private final TransitionController mController;
private final BLASTSyncEngine mSyncEngine;
private final Token mToken;
- private RemoteTransition mRemoteTransition = null;
+ private IApplicationThread mRemoteAnimApp;
/** Only use for clean-up after binder death! */
private SurfaceControl.Transaction mStartTransaction = null;
@@ -1075,12 +1075,13 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
return mForcePlaying;
}
- void setRemoteTransition(RemoteTransition remoteTransition) {
- mRemoteTransition = remoteTransition;
+ void setRemoteAnimationApp(IApplicationThread app) {
+ mRemoteAnimApp = app;
}
- RemoteTransition getRemoteTransition() {
- return mRemoteTransition;
+ /** Returns the app which will run the transition animation. */
+ IApplicationThread getRemoteAnimationApp() {
+ return mRemoteAnimApp;
}
void setNoAnimation(WindowContainer wc) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 7e267e47ede3..bcb8c46de5ed 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -567,7 +567,9 @@ class TransitionController {
transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos();
transition.mLogger.mRequest = request;
mTransitionPlayer.requestStartTransition(transition.getToken(), request);
- transition.setRemoteTransition(remoteTransition);
+ if (remoteTransition != null) {
+ transition.setRemoteAnimationApp(remoteTransition.getAppThread());
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting transition", e);
transition.start();
@@ -779,9 +781,8 @@ class TransitionController {
mRemotePlayer.clear();
return;
}
- final RemoteTransition remote = transition.getRemoteTransition();
- if (remote == null) return;
- final IApplicationThread appThread = remote.getAppThread();
+ final IApplicationThread appThread = transition.getRemoteAnimationApp();
+ if (appThread == null || appThread == mTransitionPlayerProc.getThread()) return;
final WindowProcessController delegate = mAtm.getProcessController(appThread);
if (delegate == null) return;
mRemotePlayer.update(delegate, isPlaying, true /* predict */);
diff --git a/services/core/java/com/android/server/wm/VrController.java b/services/core/java/com/android/server/wm/VrController.java
index 9e159aba4d77..241a8ae88ae7 100644
--- a/services/core/java/com/android/server/wm/VrController.java
+++ b/services/core/java/com/android/server/wm/VrController.java
@@ -126,6 +126,9 @@ final class VrController {
}
};
+ /** If it is null after system ready, then VR mode is not supported. */
+ VrManagerInternal mVrService;
+
/**
* Create new VrController instance.
*
@@ -141,6 +144,7 @@ final class VrController {
public void onSystemReady() {
VrManagerInternal vrManagerInternal = LocalServices.getService(VrManagerInternal.class);
if (vrManagerInternal != null) {
+ mVrService = vrManagerInternal;
vrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
}
}
@@ -181,7 +185,7 @@ final class VrController {
public boolean onVrModeChanged(ActivityRecord record) {
// This message means that the top focused activity enabled VR mode (or an activity
// that previously set this has become focused).
- VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
+ final VrManagerInternal vrService = mVrService;
if (vrService == null) {
// VR mode isn't supported on this device.
return false;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 10bedd4b921f..adc0595f305b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -30,7 +30,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.content.Context;
import android.os.Trace;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TimeUtils;
import android.view.Choreographer;
import android.view.SurfaceControl;
@@ -66,7 +65,6 @@ public class WindowAnimator {
int mBulkUpdateParams = 0;
Object mLastWindowFreezeSource;
- SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
private boolean mInitialized = false;
private Choreographer mChoreographer;
@@ -98,8 +96,7 @@ public class WindowAnimator {
mAnimationFrameCallback = frameTimeNs -> {
synchronized (mService.mGlobalLock) {
mAnimationFrameCallbackScheduled = false;
- final long vsyncId = mChoreographer.getVsyncId();
- animate(frameTimeNs, vsyncId);
+ animate(frameTimeNs);
if (mNotifyWhenNoAnimation && !mLastRootAnimating) {
mService.mGlobalLock.notifyAll();
}
@@ -107,21 +104,11 @@ public class WindowAnimator {
};
}
- void addDisplayLocked(final int displayId) {
- // Create the DisplayContentsAnimator object by retrieving it if the associated
- // {@link DisplayContent} exists.
- getDisplayContentsAnimatorLocked(displayId);
- }
-
- void removeDisplayLocked(final int displayId) {
- mDisplayContentsAnimators.delete(displayId);
- }
-
void ready() {
mInitialized = true;
}
- private void animate(long frameTimeNs, long vsyncId) {
+ private void animate(long frameTimeNs) {
if (!mInitialized) {
return;
}
@@ -145,10 +132,9 @@ public class WindowAnimator {
final AccessibilityController accessibilityController =
mService.mAccessibilityController;
- final int numDisplays = mDisplayContentsAnimators.size();
+ final int numDisplays = root.getChildCount();
for (int i = 0; i < numDisplays; i++) {
- final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = root.getDisplayContent(displayId);
+ final DisplayContent dc = root.getChildAt(i);
// Update animations of all applications, including those associated with
// exiting/removed apps.
dc.updateWindowsForAnimator();
@@ -156,12 +142,11 @@ public class WindowAnimator {
}
for (int i = 0; i < numDisplays; i++) {
- final int displayId = mDisplayContentsAnimators.keyAt(i);
- final DisplayContent dc = root.getDisplayContent(displayId);
+ final DisplayContent dc = root.getChildAt(i);
dc.checkAppWindowsReadyToShow();
if (accessibilityController.hasCallbacks()) {
- accessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId,
+ accessibilityController.drawMagnifiedRegionBorderIfNeeded(dc.mDisplayId,
mTransaction);
}
}
@@ -237,12 +222,9 @@ public class WindowAnimator {
public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) {
final String subPrefix = " " + prefix;
- for (int i = 0; i < mDisplayContentsAnimators.size(); i++) {
- pw.print(prefix); pw.print("DisplayContentsAnimator #");
- pw.print(mDisplayContentsAnimators.keyAt(i));
- pw.println(":");
- final DisplayContent dc =
- mService.mRoot.getDisplayContent(mDisplayContentsAnimators.keyAt(i));
+ for (int i = 0; i < mService.mRoot.getChildCount(); i++) {
+ final DisplayContent dc = mService.mRoot.getChildAt(i);
+ pw.print(prefix); pw.print(dc); pw.println(":");
dc.dumpWindowAnimators(pw, subPrefix);
pw.println();
}
@@ -260,23 +242,6 @@ public class WindowAnimator {
}
}
- private DisplayContentsAnimator getDisplayContentsAnimatorLocked(int displayId) {
- if (displayId < 0) {
- return null;
- }
-
- DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId);
-
- // It is possible that this underlying {@link DisplayContent} has been removed. In this
- // case, we do not want to create an animator associated with it as {link #animate} will
- // fail.
- if (displayAnimator == null && mService.mRoot.getDisplayContent(displayId) != null) {
- displayAnimator = new DisplayContentsAnimator();
- mDisplayContentsAnimators.put(displayId, displayAnimator);
- }
- return displayAnimator;
- }
-
void scheduleAnimation() {
if (!mAnimationFrameCallbackScheduled) {
mAnimationFrameCallbackScheduled = true;
@@ -291,9 +256,6 @@ public class WindowAnimator {
}
}
- private class DisplayContentsAnimator {
- }
-
boolean isAnimationScheduled() {
return mAnimationFrameCallbackScheduled;
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index e65b9f39e31c..531a6bdc0130 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -160,12 +160,10 @@ public final class CredentialManagerService
int resolvedUserId, boolean disabled, String[] serviceNames) {
getOrConstructSystemServiceListLock(resolvedUserId);
if (serviceNames == null || serviceNames.length == 0) {
- Slog.i(TAG, "serviceNames sent in newServiceListLocked is null, or empty");
return new ArrayList<>();
}
List<CredentialManagerServiceImpl> serviceList = new ArrayList<>(serviceNames.length);
for (String serviceName : serviceNames) {
- Log.i(TAG, "in newServiceListLocked, service: " + serviceName);
if (TextUtils.isEmpty(serviceName)) {
continue;
}
@@ -173,7 +171,7 @@ public final class CredentialManagerService
serviceList.add(
new CredentialManagerServiceImpl(this, mLock, resolvedUserId, serviceName));
} catch (PackageManager.NameNotFoundException | SecurityException e) {
- Log.i(TAG, "Unable to add serviceInfo : " + e.getMessage());
+ Slog.e(TAG, "Unable to add serviceInfo : ", e);
}
}
return serviceList;
@@ -423,7 +421,7 @@ public final class CredentialManagerService
userId);
callingAppInfo = new CallingAppInfo(realPackageName, packageInfo.signingInfo, origin);
} catch (PackageManager.NameNotFoundException e) {
- Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
+ Slog.e(TAG, "Issue while retrieving signatureInfo : ", e);
callingAppInfo = new CallingAppInfo(realPackageName, null, origin);
}
return callingAppInfo;
@@ -436,7 +434,8 @@ public final class CredentialManagerService
IGetCredentialCallback callback,
final String callingPackage) {
final long timestampBegan = System.nanoTime();
- Log.i(TAG, "starting executeGetCredential with callingPackage: " + callingPackage);
+ Slog.d(TAG, "starting executeGetCredential with callingPackage: "
+ + callingPackage);
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
if (request.getOrigin() != null) {
@@ -630,11 +629,10 @@ public final class CredentialManagerService
GetCredentialException.TYPE_NO_CREDENTIAL,
"No credentials available on this device.");
} catch (RemoteException e) {
- Log.i(
+ Slog.e(
TAG,
"Issue invoking onError on IGetCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: ", e);
}
}
@@ -649,7 +647,7 @@ public final class CredentialManagerService
ICreateCredentialCallback callback,
String callingPackage) {
final long timestampBegan = System.nanoTime();
- Log.i(TAG, "starting executeCreateCredential with callingPackage: "
+ Slog.d(TAG, "starting executeCreateCredential with callingPackage: "
+ callingPackage);
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
@@ -692,11 +690,10 @@ public final class CredentialManagerService
CreateCredentialException.TYPE_NO_CREATE_OPTIONS,
"No create options available.");
} catch (RemoteException e) {
- Log.i(
+ Slog.e(
TAG,
"Issue invoking onError on ICreateCredentialCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: ", e);
}
}
@@ -712,21 +709,19 @@ public final class CredentialManagerService
MetricUtilities.logApiCalledInitialPhase(initMetric,
session.mRequestSessionMetric.returnIncrementSequence());
} catch (Exception e) {
- Log.w(TAG, "Unexpected error during metric logging: " + e);
+ Log.w(TAG, "Unexpected error during metric logging: ", e);
}
}
@Override
public void setEnabledProviders(
List<String> providers, int userId, ISetEnabledProvidersCallback callback) {
- Log.i(TAG, "setEnabledProviders");
-
if (!hasWriteSecureSettingsPermission()) {
try {
callback.onError(
PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
} catch (RemoteException e) {
- Log.e(TAG, "Issue with invoking response: " + e.getMessage());
+ Slog.e(TAG, "Issue with invoking response: ", e);
}
return;
}
@@ -753,7 +748,7 @@ public final class CredentialManagerService
"failed_setting_store",
"Failed to store setting containing enabled providers");
} catch (RemoteException e) {
- Log.i(TAG, "Issue with invoking error response: " + e.getMessage());
+ Slog.e(TAG, "Issue with invoking error response: ", e);
return;
}
}
@@ -762,7 +757,7 @@ public final class CredentialManagerService
try {
callback.onResponse();
} catch (RemoteException e) {
- Log.i(TAG, "Issue with invoking response: " + e.getMessage());
+ Slog.e(TAG, "Issue with invoking response: ", e);
// TODO: Propagate failure
}
@@ -774,7 +769,8 @@ public final class CredentialManagerService
@Override
public boolean isEnabledCredentialProviderService(
ComponentName componentName, String callingPackage) {
- Log.i(TAG, "isEnabledCredentialProviderService");
+ Slog.d(TAG, "isEnabledCredentialProviderService with componentName: "
+ + componentName.flattenToString());
// TODO(253157366): Check additional set of services.
final int userId = UserHandle.getCallingUserId();
@@ -792,10 +788,10 @@ public final class CredentialManagerService
MetricUtilities.logApiCalledSimpleV1(
ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
ApiStatus.FAILURE, callingUid);
- Log.w(
+ Slog.w(
TAG,
- "isEnabledCredentialProviderService: Component name does not"
- + " match package name.");
+ "isEnabledCredentialProviderService: Component name does "
+ + "not match package name.");
return false;
}
MetricUtilities.logApiCalledSimpleV1(
@@ -813,7 +809,6 @@ public final class CredentialManagerService
@Override
public List<CredentialProviderInfo> getCredentialProviderServices(
int userId, int providerFilter) {
- Log.i(TAG, "getCredentialProviderServices");
verifyGetProvidersPermission();
return CredentialProviderInfoFactory.getCredentialProviderServices(
@@ -823,7 +818,6 @@ public final class CredentialManagerService
@Override
public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
int providerFilter) {
- Log.i(TAG, "getCredentialProviderServicesForTesting");
verifyGetProvidersPermission();
final int userId = UserHandle.getCallingUserId();
@@ -844,8 +838,8 @@ public final class CredentialManagerService
.getServiceInfo().getComponentName());
} catch (NullPointerException e) {
// Safe check
- Log.i(TAG, "Skipping provider as either the providerInfo"
- + "or serviceInfo is null - weird");
+ Slog.e(TAG, "Skipping provider as either the providerInfo"
+ + " or serviceInfo is null - weird");
}
});
}
@@ -858,7 +852,8 @@ public final class CredentialManagerService
IClearCredentialStateCallback callback,
String callingPackage) {
final long timestampBegan = System.nanoTime();
- Log.i(TAG, "starting clearCredentialState with callingPackage: " + callingPackage);
+ Slog.d(TAG, "starting clearCredentialState with callingPackage: "
+ + callingPackage);
final int userId = UserHandle.getCallingUserId();
int callingUid = Binder.getCallingUid();
enforceCallingPackage(callingPackage, callingUid);
@@ -885,13 +880,13 @@ public final class CredentialManagerService
if (providerSessions.isEmpty()) {
try {
// TODO("Replace with properly defined error type")
- callback.onError("UNKNOWN", "No crdentials available on this " + "device");
+ callback.onError("UNKNOWN", "No credentials available on "
+ + "this device");
} catch (RemoteException e) {
- Log.i(
+ Slog.e(
TAG,
"Issue invoking onError on IClearCredentialStateCallback "
- + "callback: "
- + e.getMessage());
+ + "callback: ", e);
}
}
@@ -906,7 +901,7 @@ public final class CredentialManagerService
public void registerCredentialDescription(
RegisterCredentialDescriptionRequest request, String callingPackage)
throws IllegalArgumentException, NonCredentialProviderCallerException {
- Log.i(TAG, "registerCredentialDescription");
+ Slog.d(TAG, "registerCredentialDescription with callingPackage: " + callingPackage);
if (!isCredentialDescriptionApiEnabled()) {
throw new UnsupportedOperationException();
@@ -924,7 +919,9 @@ public final class CredentialManagerService
public void unregisterCredentialDescription(
UnregisterCredentialDescriptionRequest request, String callingPackage)
throws IllegalArgumentException {
- Log.i(TAG, "registerCredentialDescription");
+ Slog.d(TAG, "unregisterCredentialDescription with callingPackage: "
+ + callingPackage);
+
if (!isCredentialDescriptionApiEnabled()) {
throw new UnsupportedOperationException();
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index ee55a1ccc357..91be2a734e85 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -23,7 +23,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderInfoFactory;
-import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -41,14 +40,15 @@ public final class CredentialManagerServiceImpl extends
// TODO(b/210531) : Make final when update flow is fixed
@GuardedBy("mLock")
- @NonNull private CredentialProviderInfo mInfo;
+ @NonNull
+ private CredentialProviderInfo mInfo;
CredentialManagerServiceImpl(
@NonNull CredentialManagerService master,
@NonNull Object lock, int userId, String serviceName)
throws PackageManager.NameNotFoundException {
super(master, lock, userId);
- Log.i(TAG, "in CredentialManagerServiceImpl constructed with: " + serviceName);
+ Slog.d(TAG, "CredentialManagerServiceImpl constructed for: " + serviceName);
synchronized (mLock) {
newServiceInfoLocked(ComponentName.unflattenFromString(serviceName));
}
@@ -63,10 +63,8 @@ public final class CredentialManagerServiceImpl extends
@NonNull CredentialManagerService master,
@NonNull Object lock, int userId, CredentialProviderInfo providerInfo) {
super(master, lock, userId);
- Log.i(TAG, "in CredentialManagerServiceImpl constructed with system constructor: "
- + providerInfo.isSystemProvider()
- + " , " + providerInfo.getServiceInfo() == null ? "" :
- providerInfo.getServiceInfo().getComponentName().flattenToString());
+ Slog.d(TAG, "CredentialManagerServiceImpl constructed for: "
+ + providerInfo.getServiceInfo().getComponentName().flattenToString());
mInfo = providerInfo;
}
@@ -76,12 +74,12 @@ public final class CredentialManagerServiceImpl extends
throws PackageManager.NameNotFoundException {
// TODO : Test update flows with multiple providers
if (mInfo != null) {
- Log.i(TAG, "newServiceInfoLocked with : "
+ Slog.d(TAG, "newServiceInfoLocked, mInfo not null : "
+ mInfo.getServiceInfo().getComponentName().flattenToString() + " , "
- + serviceComponent.getPackageName());
+ + serviceComponent.flattenToString());
} else {
- Log.i(TAG, "newServiceInfoLocked with null mInfo , "
- + serviceComponent.getPackageName());
+ Slog.d(TAG, "newServiceInfoLocked, mInfo null, "
+ + serviceComponent.flattenToString());
}
mInfo = CredentialProviderInfoFactory.create(
getContext(), serviceComponent,
@@ -90,18 +88,18 @@ public final class CredentialManagerServiceImpl extends
}
/**
- * Starts a provider session and associates it with the given request session. */
+ * Starts a provider session and associates it with the given request session.
+ */
@Nullable
@GuardedBy("mLock")
public ProviderSession initiateProviderSessionForRequestLocked(
RequestSession requestSession, List<String> requestOptions) {
if (!requestOptions.isEmpty() && !isServiceCapableLocked(requestOptions)) {
- Log.i(TAG, "Service is not capable");
+ Slog.d(TAG, "Service does not have the required capabilities");
return null;
}
- Slog.i(TAG, "in initiateProviderSessionForRequest in CredManServiceImpl");
if (mInfo == null) {
- Slog.i(TAG, "in initiateProviderSessionForRequest in CredManServiceImpl, "
+ Slog.w(TAG, "in initiateProviderSessionForRequest in CredManServiceImpl, "
+ "but mInfo is null. This shouldn't happen");
return null;
}
@@ -114,15 +112,11 @@ public final class CredentialManagerServiceImpl extends
@GuardedBy("mLock")
boolean isServiceCapableLocked(List<String> requestedOptions) {
if (mInfo == null) {
- Slog.i(TAG, "in isServiceCapable, mInfo is null");
return false;
}
for (String capability : requestedOptions) {
if (mInfo.hasCapability(capability)) {
- Slog.i(TAG, "Provider can handle: " + capability);
return true;
- } else {
- Slog.i(TAG, "Provider cannot handle: " + capability);
}
}
return false;
@@ -146,7 +140,7 @@ public final class CredentialManagerServiceImpl extends
try {
newServiceInfoLocked(mInfo.getServiceInfo().getComponentName());
} catch (PackageManager.NameNotFoundException e) {
- Log.i(TAG, "Issue while updating serviceInfo: " + e.getMessage());
+ Slog.e(TAG, "Issue while updating serviceInfo: " + e.getMessage());
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2479646e4561..b5a5d94486da 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10617,38 +10617,59 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* - SYSTEM_UID
* - adb unless hasIncompatibleAccountsOrNonAdb is true.
*/
+ @GuardedBy("getLockObject()")
private void enforceCanSetProfileOwnerLocked(
- CallerIdentity caller, @Nullable ComponentName owner, int userHandle,
+ CallerIdentity caller, @Nullable ComponentName owner, @UserIdInt int userId,
boolean hasIncompatibleAccountsOrNonAdb) {
- UserInfo info = getUserInfo(userHandle);
+ UserInfo info = getUserInfo(userId);
if (info == null) {
// User doesn't exist.
throw new IllegalArgumentException(
- "Attempted to set profile owner for invalid userId: " + userHandle);
+ "Attempted to set profile owner for invalid userId: " + userId);
}
if (info.isGuest()) {
throw new IllegalStateException("Cannot set a profile owner on a guest");
}
- if (mOwners.hasProfileOwner(userHandle)) {
- throw new IllegalStateException("Trying to set the profile owner, but profile owner "
- + "is already set.");
+ if (mOwners.hasProfileOwner(userId)) {
+ StringBuilder errorMessage = new StringBuilder("Trying to set the profile owner");
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ append(errorMessage, owner).append(" on user ").append(userId);
+ }
+ errorMessage.append(", but profile owner");
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ appendProfileOwnerLocked(errorMessage, userId);
+ }
+
+ throw new IllegalStateException(errorMessage.append(" is already set.").toString());
}
- if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userHandle) {
- throw new IllegalStateException("Trying to set the profile owner, but the user "
- + "already has a device owner.");
+ if (mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerUserId() == userId) {
+ StringBuilder errorMessage = new StringBuilder("Trying to set the profile owner");
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ append(errorMessage, owner).append(" on user ").append(userId);
+ }
+ errorMessage.append(", but the user already has a device owner");
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ appendDeviceOwnerLocked(errorMessage);
+ }
+ throw new IllegalStateException(errorMessage.append('.').toString());
}
if (isAdb(caller)) {
- if ((mIsWatch || hasUserSetupCompleted(userHandle))
+ if ((mIsWatch || hasUserSetupCompleted(userId))
&& hasIncompatibleAccountsOrNonAdb) {
- throw new IllegalStateException("Not allowed to set the profile owner because "
- + "there are already some accounts on the profile");
+ StringBuilder errorMessage = new StringBuilder("Not allowed to set the profile "
+ + "owner");
+ if (!hasIncompatibleAccountsOrNonAdb) {
+ append(errorMessage, owner).append(" on user ").append(userId).append(' ');
+ }
+ throw new IllegalStateException(errorMessage.append(" because there are already "
+ + "some accounts on the profile.").toString());
}
return;
}
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
- if ((mIsWatch || hasUserSetupCompleted(userHandle))) {
+ if ((mIsWatch || hasUserSetupCompleted(userId))) {
Preconditions.checkState(isSystemUid(caller),
"Cannot set the profile owner on a user which is already set-up");
@@ -10665,31 +10686,62 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
* permission.
*/
+ @GuardedBy("getLockObject()")
private void enforceCanSetDeviceOwnerLocked(
CallerIdentity caller, @Nullable ComponentName owner, @UserIdInt int deviceOwnerUserId,
boolean hasIncompatibleAccountsOrNonAdb) {
+ boolean showComponentOnError = false;
if (!isAdb(caller)) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
+ } else {
+ showComponentOnError = true;
}
final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner,
/* deviceOwnerUserId= */ deviceOwnerUserId, /* callingUserId*/ caller.getUserId(),
isAdb(caller), hasIncompatibleAccountsOrNonAdb);
if (code != STATUS_OK) {
- throw new IllegalStateException(
- computeProvisioningErrorString(code, deviceOwnerUserId));
+ throw new IllegalStateException(computeProvisioningErrorStringLocked(code,
+ deviceOwnerUserId, owner, showComponentOnError));
+ }
+ }
+
+ private String computeProvisioningErrorString(int code, @UserIdInt int userId) {
+ synchronized (getLockObject()) {
+ return computeProvisioningErrorStringLocked(code, userId, /* newOwner= */ null,
+ /* showComponentOnError= */ false);
}
}
- private static String computeProvisioningErrorString(int code, @UserIdInt int userId) {
+ @GuardedBy("getLockObject()")
+ private String computeProvisioningErrorStringLocked(int code, @UserIdInt int userId,
+ @Nullable ComponentName newOwner, boolean showComponentOnError) {
switch (code) {
case STATUS_OK:
return "OK";
- case STATUS_HAS_DEVICE_OWNER:
- return "Trying to set the device owner, but device owner is already set.";
- case STATUS_USER_HAS_PROFILE_OWNER:
- return "Trying to set the device owner, but the user already has a profile owner.";
+ case STATUS_HAS_DEVICE_OWNER: {
+ StringBuilder error = new StringBuilder("Trying to set the device owner");
+ if (showComponentOnError && newOwner != null) {
+ append(error, newOwner);
+ }
+ error.append(", but device owner");
+ if (showComponentOnError) {
+ appendDeviceOwnerLocked(error);
+ }
+ return error.append(" is already set.").toString();
+ }
+ case STATUS_USER_HAS_PROFILE_OWNER: {
+ StringBuilder error = new StringBuilder("Trying to set the device owner");
+ if (showComponentOnError && newOwner != null) {
+ append(error, newOwner);
+ }
+ error.append(", but the user already has a profile owner");
+ if (showComponentOnError) {
+ appendProfileOwnerLocked(error, userId);
+ }
+ return error.append(".").toString();
+ }
case STATUS_USER_NOT_RUNNING:
return "User " + userId + " not running.";
case STATUS_NOT_SYSTEM_USER:
@@ -10708,7 +10760,32 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
default:
return "Unexpected @ProvisioningPreCondition: " + code;
}
+ }
+ @GuardedBy("getLockObject()")
+ private void appendDeviceOwnerLocked(StringBuilder string) {
+ ComponentName deviceOwner = getDeviceOwnerComponent(/* callingUserOnly= */ false);
+ if (deviceOwner == null) {
+ // Shouldn't happen, but it doesn't hurt to check...
+ Slogf.wtf(LOG_TAG, "appendDeviceOwnerLocked(): device has no DO set");
+ return;
+ }
+ append(string, deviceOwner);
+ }
+
+ @GuardedBy("getLockObject()")
+ private void appendProfileOwnerLocked(StringBuilder string, @UserIdInt int userId) {
+ ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
+ if (profileOwner == null) {
+ // Shouldn't happen, but it doesn't hurt to check...
+ Slogf.wtf(LOG_TAG, "profileOwner(%d): PO not set", userId);
+ return;
+ }
+ append(string, profileOwner);
+ }
+
+ private static StringBuilder append(StringBuilder string, ComponentName component) {
+ return string.append(" (").append(component.flattenToShortString()).append(')');
}
private void enforceUserUnlocked(int userId) {
@@ -19654,7 +19731,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public void setApplicationExemptions(String packageName, int[] exemptions) {
+ public void setApplicationExemptions(String callerPackage, String packageName,
+ int[] exemptions) {
if (!mHasFeature) {
return;
}
@@ -19665,7 +19743,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS));
- final CallerIdentity caller = getCallerIdentity();
+ final CallerIdentity caller = getCallerIdentity(callerPackage);
final ApplicationInfo packageInfo;
packageInfo = getPackageInfoWithNullCheck(packageName, caller);
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 8994a488bd56..ab8f3f2279fe 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -383,6 +383,7 @@ public class UserControllerTest {
// Call dispatchUserSwitch and verify that observer was called only once
mInjector.mHandler.clearAllRecordedMessages();
mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
+ verify(observer, times(1)).onBeforeUserSwitching(eq(TEST_USER_ID));
verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
Set<Integer> expectedCodes = Collections.singleton(CONTINUE_USER_SWITCH_MSG);
Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
@@ -413,6 +414,7 @@ public class UserControllerTest {
// Call dispatchUserSwitch and verify that observer was called only once
mInjector.mHandler.clearAllRecordedMessages();
mUserController.dispatchUserSwitch(userState, oldUserId, newUserId);
+ verify(observer, times(1)).onBeforeUserSwitching(eq(TEST_USER_ID));
verify(observer, times(1)).onUserSwitching(eq(TEST_USER_ID), any());
// Verify that CONTINUE_USER_SWITCH_MSG is not sent (triggers timeout)
Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes();
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index e8e3a8f84f21..09ee59816a2c 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -32,6 +32,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index 182bf949af1f..82bc6f6c5263 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -16,8 +16,10 @@ package com.android.server;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
+import android.content.Intent;
import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.Build;
@@ -44,8 +46,8 @@ public class UiServiceTestCase {
protected static final String PKG_R = "com.example.r";
@Rule
- public final TestableContext mContext =
- new TestableContext(InstrumentationRegistry.getContext(), null);
+ public TestableContext mContext =
+ spy(new TestableContext(InstrumentationRegistry.getContext(), null));
protected TestableContext getContext() {
return mContext;
@@ -81,6 +83,11 @@ public class UiServiceTestCase {
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
when(mUgmInternal.checkGrantUriPermission(
anyInt(), anyString(), any(Uri.class), anyInt(), anyInt())).thenReturn(-1);
+
+ Mockito.doReturn(new Intent()).when(mContext).registerReceiverAsUser(
+ any(), any(), any(), any(), any());
+ Mockito.doReturn(new Intent()).when(mContext).registerReceiver(any(), any());
+ Mockito.doNothing().when(mContext).unregisterReceiver(any());
}
@After
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index ce076217f37b..8fcbf2f9e97a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -130,13 +130,18 @@ public class ManagedServicesTest extends UiServiceTestCase {
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedPrimary;
private ArrayMap<Integer, ArrayMap<Integer, String>> mExpectedSecondary;
+ private UserHandle mUser;
+ private String mPkg;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- getContext().setMockPackageManager(mPm);
- getContext().addMockSystemService(Context.USER_SERVICE, mUm);
- getContext().addMockSystemService(DEVICE_POLICY_SERVICE, mDpm);
+ mContext.setMockPackageManager(mPm);
+ mContext.addMockSystemService(Context.USER_SERVICE, mUm);
+ mContext.addMockSystemService(DEVICE_POLICY_SERVICE, mDpm);
+ mUser = mContext.getUser();
+ mPkg = mContext.getPackageName();
List<UserInfo> users = new ArrayList<>();
users.add(mZero);
@@ -861,8 +866,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -891,8 +896,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -921,8 +926,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -951,8 +956,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -981,8 +986,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1011,8 +1016,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1437,8 +1442,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1464,8 +1469,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1492,8 +1497,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1522,8 +1527,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1552,8 +1557,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1791,8 +1796,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1837,8 +1842,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
@@ -1880,8 +1885,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
ApplicationInfo ai = new ApplicationInfo();
ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
- when(context.getPackageName()).thenReturn(mContext.getPackageName());
- when(context.getUserId()).thenReturn(mContext.getUserId());
+ when(context.getPackageName()).thenReturn(mPkg);
+ when(context.getUserId()).thenReturn(mUser.getIdentifier());
when(context.getPackageManager()).thenReturn(pm);
when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
index d73a3b8e44a6..95fae0707304 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
@@ -33,9 +33,11 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.os.UserHandle;
@@ -63,7 +65,7 @@ import java.util.List;
@SmallTest
@RunWith(Parameterized.class)
public class NotificationComparatorTest extends UiServiceTestCase {
- @Mock Context mContext;
+ @Mock Context mMockContext;
@Mock TelecomManager mTm;
@Mock RankingHandler handler;
@Mock PackageManager mPm;
@@ -115,32 +117,35 @@ public class NotificationComparatorTest extends UiServiceTestCase {
int userId = UserHandle.myUserId();
- when(mContext.getResources()).thenReturn(getContext().getResources());
- when(mContext.getTheme()).thenReturn(getContext().getTheme());
- when(mContext.getContentResolver()).thenReturn(getContext().getContentResolver());
- when(mContext.getPackageManager()).thenReturn(mPm);
- when(mContext.getSystemService(eq(Context.TELECOM_SERVICE))).thenReturn(mTm);
- when(mContext.getSystemService(Vibrator.class)).thenReturn(mVibrator);
- when(mContext.getString(anyInt())).thenCallRealMethod();
- when(mContext.getColor(anyInt())).thenCallRealMethod();
+ final Resources res = mContext.getResources();
+ when(mMockContext.getResources()).thenReturn(res);
+ final Resources.Theme theme = mContext.getTheme();
+ when(mMockContext.getTheme()).thenReturn(theme);
+ final ContentResolver cr = mContext.getContentResolver();
+ when(mMockContext.getContentResolver()).thenReturn(cr);
+ when(mMockContext.getPackageManager()).thenReturn(mPm);
+ when(mMockContext.getSystemService(eq(mMockContext.TELECOM_SERVICE))).thenReturn(mTm);
+ when(mMockContext.getSystemService(Vibrator.class)).thenReturn(mVibrator);
+ when(mMockContext.getString(anyInt())).thenCallRealMethod();
+ when(mMockContext.getColor(anyInt())).thenCallRealMethod();
when(mTm.getDefaultDialerPackage()).thenReturn(callPkg);
final ApplicationInfo legacy = new ApplicationInfo();
legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
try {
when(mPm.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())).thenReturn(legacy);
- when(mContext.getApplicationInfo()).thenReturn(legacy);
+ when(mMockContext.getApplicationInfo()).thenReturn(legacy);
} catch (PackageManager.NameNotFoundException e) {
// let's hope not
}
- smsPkg = Settings.Secure.getString(mContext.getContentResolver(),
+ smsPkg = Settings.Secure.getString(mMockContext.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION);
- Notification nonInterruptiveNotif = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification nonInterruptiveNotif = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_CALL)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordMinCallNonInterruptive = new NotificationRecord(mContext,
+ mRecordMinCallNonInterruptive = new NotificationRecord(mMockContext,
new StatusBarNotification(callPkg,
callPkg, 1, "mRecordMinCallNonInterruptive", callUid, callUid,
nonInterruptiveNotif,
@@ -148,134 +153,134 @@ public class NotificationComparatorTest extends UiServiceTestCase {
mRecordMinCallNonInterruptive.setSystemImportance(NotificationManager.IMPORTANCE_MIN);
mRecordMinCallNonInterruptive.setInterruptive(false);
- Notification n1 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n1 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_CALL)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordMinCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
+ mRecordMinCall = new NotificationRecord(mMockContext, new StatusBarNotification(callPkg,
callPkg, 1, "minCall", callUid, callUid, n1,
new UserHandle(userId), "", 2000), getDefaultChannel());
mRecordMinCall.setSystemImportance(NotificationManager.IMPORTANCE_MIN);
mRecordMinCall.setInterruptive(true);
- Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n2 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_CALL)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
+ mRecordHighCall = new NotificationRecord(mMockContext, new StatusBarNotification(callPkg,
callPkg, 1, "highcall", callUid, callUid, n2,
new UserHandle(userId), "", 1999), getDefaultChannel());
mRecordHighCall.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
- Notification nHighCallStyle = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification nHighCallStyle = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setStyle(Notification.CallStyle.forOngoingCall(
new Person.Builder().setName("caller").build(),
mock(PendingIntent.class)
))
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordHighCallStyle = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
- callPkg, 1, "highCallStyle", callUid, callUid, nHighCallStyle,
+ mRecordHighCallStyle = new NotificationRecord(mMockContext, new StatusBarNotification(
+ callPkg, callPkg, 1, "highCallStyle", callUid, callUid, nHighCallStyle,
new UserHandle(userId), "", 2000), getDefaultChannel());
mRecordHighCallStyle.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
mRecordHighCallStyle.setInterruptive(true);
- Notification n4 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n4 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setStyle(new Notification.MessagingStyle("sender!")).build();
- mRecordInlineReply = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ mRecordInlineReply = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "inlinereply", uid2, uid2, n4, new UserHandle(userId),
"", 1599), getDefaultChannel());
mRecordInlineReply.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
mRecordInlineReply.setPackagePriority(Notification.PRIORITY_MAX);
if (smsPkg != null) {
- Notification n5 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n5 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_MESSAGE).build();
- mRecordSms = new NotificationRecord(mContext, new StatusBarNotification(smsPkg,
+ mRecordSms = new NotificationRecord(mMockContext, new StatusBarNotification(smsPkg,
smsPkg, 1, "sms", smsUid, smsUid, n5, new UserHandle(userId),
"", 1299), getDefaultChannel());
mRecordSms.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
}
- Notification n6 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
- mRecordStarredContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ Notification n6 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID).build();
+ mRecordStarredContact = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "starred", uid2, uid2, n6, new UserHandle(userId),
"", 1259), getDefaultChannel());
mRecordStarredContact.setContactAffinity(ValidateNotificationPeople.STARRED_CONTACT);
mRecordStarredContact.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
- Notification n7 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
- mRecordContact = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ Notification n7 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID).build();
+ mRecordContact = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "contact", uid2, uid2, n7, new UserHandle(userId),
"", 1259), getDefaultChannel());
mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
mRecordContact.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
- Notification nSystemMax = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
- mRecordSystemMax = new NotificationRecord(mContext, new StatusBarNotification(sysPkg,
+ Notification nSystemMax = new Notification.Builder(mMockContext, TEST_CHANNEL_ID).build();
+ mRecordSystemMax = new NotificationRecord(mMockContext, new StatusBarNotification(sysPkg,
sysPkg, 1, "systemmax", uid2, uid2, nSystemMax, new UserHandle(userId),
"", 1244), getDefaultChannel());
mRecordSystemMax.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
- Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
- mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ Notification n8 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID).build();
+ mRecordUrgent = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
"", 1258), getDefaultChannel());
mRecordUrgent.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
- Notification n9 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n9 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_MESSAGE)
.setFlag(Notification.FLAG_ONGOING_EVENT
|Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordCheater = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ mRecordCheater = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
"", 9258), getDefaultChannel());
mRecordCheater.setSystemImportance(NotificationManager.IMPORTANCE_LOW);
mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
- Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n10 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
- mRecordEmail = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ mRecordEmail = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
"", 1599), getDefaultChannel());
mRecordEmail.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
- Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n11 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_MESSAGE)
.setColorized(true).setColor(Color.WHITE)
.build();
- mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
- pkg2, 1, "cheaterColorized", uid2, uid2, n11, new UserHandle(userId),
- "", 9258), getDefaultChannel());
+ mRecordCheaterColorized = new NotificationRecord(mMockContext,
+ new StatusBarNotification(pkg2,pkg2, 1, "cheaterColorized", uid2, uid2, n11,
+ new UserHandle(userId), "", 9258), getDefaultChannel());
mRecordCheaterColorized.setSystemImportance(NotificationManager.IMPORTANCE_LOW);
- Notification n12 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n12 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_MESSAGE)
.setColorized(true).setColor(Color.WHITE)
.setStyle(new Notification.MediaStyle())
.build();
- mNoMediaSessionMedia = new NotificationRecord(mContext, new StatusBarNotification(
+ mNoMediaSessionMedia = new NotificationRecord(mMockContext, new StatusBarNotification(
pkg2, pkg2, 1, "media", uid2, uid2, n12, new UserHandle(userId),
"", 9258), getDefaultChannel());
mNoMediaSessionMedia.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
- Notification n13 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n13 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.setColorized(true).setColor(Color.WHITE)
.build();
- mRecordColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ mRecordColorized = new NotificationRecord(mMockContext, new StatusBarNotification(pkg2,
pkg2, 1, "colorized", uid2, uid2, n13,
new UserHandle(userId), "", 1999), getDefaultChannel());
mRecordColorized.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
- Notification n14 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ Notification n14 = new Notification.Builder(mMockContext, TEST_CHANNEL_ID)
.setCategory(Notification.CATEGORY_CALL)
.setColorized(true).setColor(Color.WHITE)
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
.build();
- mRecordColorizedCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
- callPkg, 1, "colorizedCall", callUid, callUid, n14,
+ mRecordColorizedCall = new NotificationRecord(mMockContext, new StatusBarNotification(
+ callPkg, callPkg, 1, "colorizedCall", callUid, callUid, n14,
new UserHandle(userId), "", 1999), getDefaultChannel());
mRecordColorizedCall.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
}
@@ -316,14 +321,14 @@ public class NotificationComparatorTest extends UiServiceTestCase {
actual.addAll(expected);
Collections.shuffle(actual);
- Collections.sort(actual, new NotificationComparator(mContext));
+ Collections.sort(actual, new NotificationComparator(mMockContext));
assertThat(actual).containsExactlyElementsIn(expected).inOrder();
}
@Test
public void testRankingScoreOverrides() {
- NotificationComparator comp = new NotificationComparator(mContext);
+ NotificationComparator comp = new NotificationComparator(mMockContext);
NotificationRecord recordMinCallNonInterruptive = spy(mRecordMinCallNonInterruptive);
if (mSortByInterruptiveness) {
assertTrue(comp.compare(mRecordMinCall, recordMinCallNonInterruptive) < 0);
@@ -339,7 +344,7 @@ public class NotificationComparatorTest extends UiServiceTestCase {
@Test
public void testMessaging() {
- NotificationComparator comp = new NotificationComparator(mContext);
+ NotificationComparator comp = new NotificationComparator(mMockContext);
assertTrue(comp.isImportantMessaging(mRecordInlineReply));
if (mRecordSms != null) {
assertTrue(comp.isImportantMessaging(mRecordSms));
@@ -350,7 +355,7 @@ public class NotificationComparatorTest extends UiServiceTestCase {
@Test
public void testPeople() {
- NotificationComparator comp = new NotificationComparator(mContext);
+ NotificationComparator comp = new NotificationComparator(mMockContext);
assertTrue(comp.isImportantPeople(mRecordStarredContact));
assertTrue(comp.isImportantPeople(mRecordContact));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 1b42fd3bb241..60f1e66b7e94 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -30,6 +30,7 @@ import android.app.NotificationHistory.HistoricalNotification;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Handler;
+import android.os.UserHandle;
import android.util.AtomicFile;
import androidx.test.InstrumentationRegistry;
@@ -56,8 +57,6 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
File mRootDir;
@Mock
Handler mFileWriteHandler;
- @Mock
- Context mContext;
NotificationHistoryDatabase mDataBase;
@@ -92,10 +91,8 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mContext.getUser()).thenReturn(getContext().getUser());
- when(mContext.getPackageName()).thenReturn(getContext().getPackageName());
-
- mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest");
+ final File fileDir = mContext.getFilesDir();
+ mRootDir = new File(fileDir, "NotificationHistoryDatabaseTest");
mDataBase = new NotificationHistoryDatabase(mFileWriteHandler, mRootDir);
mDataBase.init();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9ca8d8444df9..42d1ace37ba5 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -307,7 +307,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Mock
private PermissionHelper mPermissionHelper;
private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake();
- private TestableContext mContext = spy(getContext());
private final String PKG = mContext.getPackageName();
private TestableLooper mTestableLooper;
@Mock
@@ -425,7 +424,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// Shell permisssions will override permissions of our app, so add all necessary permissions
// for this test here:
InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
- "android.permission.ALLOWLISTED_WRITE_DEVICE_CONFIG",
+ "android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG",
"android.permission.READ_DEVICE_CONFIG",
"android.permission.READ_CONTACTS");
@@ -578,9 +577,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
ArgumentCaptor<IntentFilter> intentFilterCaptor =
ArgumentCaptor.forClass(IntentFilter.class);
- Mockito.doReturn(new Intent()).when(mContext).registerReceiverAsUser(
- any(), any(), any(), any(), any());
- Mockito.doReturn(new Intent()).when(mContext).registerReceiver(any(), any());
verify(mContext, atLeastOnce()).registerReceiverAsUser(broadcastReceiverCaptor.capture(),
any(), intentFilterCaptor.capture(), any(), any());
verify(mContext, atLeastOnce()).registerReceiver(broadcastReceiverCaptor.capture(),
@@ -611,6 +607,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
anyString(), anyInt(), any())).thenReturn(true);
when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true);
+ mockIsUserVisible(DEFAULT_DISPLAY, true);
mockIsVisibleBackgroundUsersSupported(false);
// Set the testable bubble extractor
@@ -6913,6 +6910,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testTextToastsCallStatusBar_nonUiContext_secondaryDisplay()
throws Exception {
allowTestPackageToToast();
+ mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
enqueueTextToast(TEST_PACKAGE, "Text", /* isUiContext= */ false, SECONDARY_DISPLAY_ID);
@@ -6936,6 +6934,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testTextToastsCallStatusBar_visibleBgUsers_uiContext_secondaryDisplay()
throws Exception {
mockIsVisibleBackgroundUsersSupported(true);
+ mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
allowTestPackageToToast();
@@ -6960,6 +6959,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testTextToastsCallStatusBar_visibleBgUsers_nonUiContext_secondaryDisplay()
throws Exception {
mockIsVisibleBackgroundUsersSupported(true);
+ mockIsUserVisible(SECONDARY_DISPLAY_ID, true);
mockDisplayAssignedToUser(INVALID_DISPLAY); // make sure it's not used
allowTestPackageToToast();
@@ -6969,6 +6969,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testTextToastsCallStatusBar_userNotVisibleOnDisplay() throws Exception {
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = false;
+ setToastRateIsWithinQuota(true);
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
+ mockIsUserVisible(DEFAULT_DISPLAY, false);
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ // enqueue toast -> no toasts enqueued
+ enqueueTextToast(testPackage, "Text");
+ verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
+ anyInt());
+ assertEquals(0, mService.mToastQueue.size());
+ }
+
+ @Test
public void testDisallowToastsFromSuspendedPackages() throws Exception {
final String testPackage = "testPackageName";
assertEquals(0, mService.mToastQueue.size());
@@ -6985,6 +7005,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// enqueue toast -> no toasts enqueued
enqueueToast(testPackage, new TestableToastCallback());
+ verify(mStatusBar, never()).showToast(anyInt(), any(), any(), any(), any(), anyInt(), any(),
+ anyInt());
assertEquals(0, mService.mToastQueue.size());
}
@@ -10808,6 +10830,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mUm.isVisibleBackgroundUsersSupported()).thenReturn(supported);
}
+ private void mockIsUserVisible(int displayId, boolean visible) {
+ when(mUmInternal.isUserVisible(mUserId, displayId)).thenReturn(visible);
+ }
+
private void mockDisplayAssignedToUser(int displayId) {
when(mUmInternal.getMainDisplayAssignedToUser(mUserId)).thenReturn(displayId);
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 25e74bf5dcd2..fae92d9ac738 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -55,6 +55,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
@@ -126,7 +127,8 @@ public class NotificationRecordTest extends UiServiceTestCase {
MockitoAnnotations.initMocks(this);
when(mMockContext.getSystemService(eq(Vibrator.class))).thenReturn(mVibrator);
- when(mMockContext.getResources()).thenReturn(getContext().getResources());
+ final Resources res = mContext.getResources();
+ when(mMockContext.getResources()).thenReturn(res);
when(mMockContext.getPackageManager()).thenReturn(mPm);
when(mMockContext.getContentResolver()).thenReturn(mContentResolver);
ApplicationInfo appInfo = new ApplicationInfo();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
index fcff228fb591..0222bfbf8605 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
@@ -67,7 +67,6 @@ import java.util.List;
public class NotificationShellCmdTest extends UiServiceTestCase {
private final Binder mBinder = new Binder();
private final ShellCallback mCallback = new ShellCallback();
- private final TestableContext mTestableContext = spy(getContext());
@Mock
NotificationManagerService mMockService;
@Mock
@@ -82,7 +81,7 @@ public class NotificationShellCmdTest extends UiServiceTestCase {
mTestableLooper = TestableLooper.get(this);
mResultReceiver = new ResultReceiver(new Handler(mTestableLooper.getLooper()));
- when(mMockService.getContext()).thenReturn(mTestableContext);
+ when(mMockService.getContext()).thenReturn(mContext);
when(mMockService.getBinderService()).thenReturn(mMockBinderService);
}
@@ -116,9 +115,10 @@ public class NotificationShellCmdTest extends UiServiceTestCase {
Notification captureNotification(String aTag) throws Exception {
ArgumentCaptor<Notification> notificationCaptor =
ArgumentCaptor.forClass(Notification.class);
+ final String pkg = getContext().getPackageName();
verify(mMockBinderService).enqueueNotificationWithTag(
- eq(getContext().getPackageName()),
- eq(getContext().getPackageName()),
+ eq(pkg),
+ eq(pkg),
eq(aTag),
eq(NotificationShellCmd.NOTIFICATION_ID),
notificationCaptor.capture(),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index bf836ae0eba0..6f9798ea7d69 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -153,7 +153,6 @@ public class ZenModeHelperTest extends UiServiceTestCase {
private Resources mResources;
private TestableLooper mTestableLooper;
private ZenModeHelper mZenModeHelperSpy;
- private Context mContext;
private ContentResolver mContentResolver;
@Mock AppOpsManager mAppOps;
private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory;
@@ -163,9 +162,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
- mContext = spy(getContext());
mContentResolver = mContext.getContentResolver();
mResources = spy(mContext.getResources());
+ String pkg = mContext.getPackageName();
try {
when(mResources.getXml(R.xml.default_zen_mode_config)).thenReturn(
getDefaultConfigParser());
@@ -190,7 +189,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt()))
.thenReturn(CUSTOM_PKG_UID);
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
- new String[] {getContext().getPackageName()});
+ new String[] {pkg});
mZenModeHelperSpy.mPm = mPackageManager;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 3eabea67e890..48a39e682340 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -621,8 +621,13 @@ final class HotwordDetectionConnection {
ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed,
int detectionServiceType) {
mIntent = intent;
- mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
mDetectionServiceType = detectionServiceType;
+ int flags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
+ if (mVisualQueryDetectionComponentName != null
+ && mHotwordDetectionComponentName != null) {
+ flags |= Context.BIND_SHARED_ISOLATED_PROCESS;
+ }
+ mBindingFlags = flags;
}
ServiceConnection createLocked() {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 929e033315f7..62be2a555bc4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -738,6 +738,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
} else {
verifyDetectorForVisualQueryDetectionLocked(sharedMemory);
}
+ if (!verifyProcessSharingLocked()) {
+ Slog.w(TAG, "Sandboxed detection service not in shared isolated process");
+ throw new IllegalStateException("VisualQueryDetectionService or HotworDetectionService "
+ + "not in a shared isolated process. Please make sure to set "
+ + "android:allowSharedIsolatedProcess and android:isolatedProcess to be true "
+ + "and android:externalService to be false in the manifest file");
+ }
if (mHotwordDetectionConnection == null) {
mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext,
@@ -931,6 +938,19 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
&& (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
}
+ @GuardedBy("this")
+ boolean verifyProcessSharingLocked() {
+ // only check this if both VQDS and HDS are declared in the app
+ ServiceInfo hotwordInfo = getServiceInfoLocked(mHotwordDetectionComponentName, mUser);
+ ServiceInfo visualQueryInfo =
+ getServiceInfoLocked(mVisualQueryDetectionComponentName, mUser);
+ if (hotwordInfo == null || visualQueryInfo == null) {
+ return true;
+ }
+ return (hotwordInfo.flags & ServiceInfo.FLAG_ALLOW_SHARED_ISOLATED_PROCESS) != 0
+ && (visualQueryInfo.flags & ServiceInfo.FLAG_ALLOW_SHARED_ISOLATED_PROCESS) != 0;
+ }
+
void forceRestartHotwordDetector() {
if (mHotwordDetectionConnection == null) {
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 554beb9a35ba..1ce85ba93d95 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1186,7 +1186,6 @@ public class ApnSetting implements Parcelable {
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mId, other.mId)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
&& Objects.equals(mProxyAddress, other.mProxyAddress)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index 15fd817ba73b..e5ef62b16dfd 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -38,6 +38,7 @@ import android.os.RemoteException;
import android.util.Log;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import java.util.HashMap;
import java.util.List;
@@ -49,9 +50,14 @@ import java.util.concurrent.Executor;
* This class is the library used by consumers of Shared Connectivity data to bind to the service,
* receive callbacks from, and send user actions to the service.
*
+ * A client must register at least one callback so that the manager will bind to the service. Once
+ * all callbacks are unregistered, the manager will unbind from the service. When the client no
+ * longer needs Shared Connectivity data, the client must unregister.
+ *
* The methods {@link #connectHotspotNetwork}, {@link #disconnectHotspotNetwork},
* {@link #connectKnownNetwork} and {@link #forgetKnownNetwork} are not valid and will return false
- * if not called between {@link SharedConnectivityClientCallback#onServiceConnected()}
+ * and getter methods will fail and return null if not called between
+ * {@link SharedConnectivityClientCallback#onServiceConnected()}
* and {@link SharedConnectivityClientCallback#onServiceDisconnected()} or if
* {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} was called.
*
@@ -139,19 +145,22 @@ public class SharedConnectivityManager {
}
private ISharedConnectivityService mService;
+ @GuardedBy("mProxyDataLock")
private final Map<SharedConnectivityClientCallback, SharedConnectivityCallbackProxy>
mProxyMap = new HashMap<>();
+ @GuardedBy("mProxyDataLock")
private final Map<SharedConnectivityClientCallback, SharedConnectivityCallbackProxy>
mCallbackProxyCache = new HashMap<>();
- // Used for testing
- private final ServiceConnection mServiceConnection;
+ // Makes sure mProxyMap and mCallbackProxyCache are locked together when one of them is used.
+ private final Object mProxyDataLock = new Object();
+ private final Context mContext;
+ private final String mServicePackageName;
+ private final String mIntentAction;
+ private ServiceConnection mServiceConnection;
/**
* Creates a new instance of {@link SharedConnectivityManager}.
*
- * Automatically binds to implementation of {@link SharedConnectivityService} specified in
- * the device overlay.
- *
* @return An instance of {@link SharedConnectivityManager} or null if the shared connectivity
* service is not found.
* @hide
@@ -185,12 +194,18 @@ public class SharedConnectivityManager {
private SharedConnectivityManager(@NonNull Context context, String servicePackageName,
String serviceIntentAction) {
+ mContext = context;
+ mServicePackageName = servicePackageName;
+ mIntentAction = serviceIntentAction;
+ }
+
+ private void bind() {
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ISharedConnectivityService.Stub.asInterface(service);
- if (!mCallbackProxyCache.isEmpty()) {
- synchronized (mCallbackProxyCache) {
+ synchronized (mProxyDataLock) {
+ if (!mCallbackProxyCache.isEmpty()) {
mCallbackProxyCache.keySet().forEach(callback ->
registerCallbackInternal(
callback, mCallbackProxyCache.get(callback)));
@@ -203,15 +218,13 @@ public class SharedConnectivityManager {
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.i(TAG, "onServiceDisconnected");
mService = null;
- if (!mCallbackProxyCache.isEmpty()) {
- synchronized (mCallbackProxyCache) {
+ synchronized (mProxyDataLock) {
+ if (!mCallbackProxyCache.isEmpty()) {
mCallbackProxyCache.keySet().forEach(
SharedConnectivityClientCallback::onServiceDisconnected);
mCallbackProxyCache.clear();
}
- }
- if (!mProxyMap.isEmpty()) {
- synchronized (mProxyMap) {
+ if (!mProxyMap.isEmpty()) {
mProxyMap.keySet().forEach(
SharedConnectivityClientCallback::onServiceDisconnected);
mProxyMap.clear();
@@ -220,8 +233,8 @@ public class SharedConnectivityManager {
}
};
- context.bindService(
- new Intent().setPackage(servicePackageName).setAction(serviceIntentAction),
+ mContext.bindService(
+ new Intent().setPackage(mServicePackageName).setAction(mIntentAction),
mServiceConnection, Context.BIND_AUTO_CREATE);
}
@@ -229,7 +242,7 @@ public class SharedConnectivityManager {
SharedConnectivityCallbackProxy proxy) {
try {
mService.registerCallback(proxy);
- synchronized (mProxyMap) {
+ synchronized (mProxyDataLock) {
mProxyMap.put(callback, proxy);
}
callback.onServiceConnected();
@@ -256,10 +269,19 @@ public class SharedConnectivityManager {
return mServiceConnection;
}
+ private void unbind() {
+ if (mServiceConnection != null) {
+ mContext.unbindService(mServiceConnection);
+ mServiceConnection = null;
+ }
+ }
+
/**
* Registers a callback for receiving updates to the list of Hotspot Networks, Known Networks,
* shared connectivity settings state, hotspot network connection status and known network
* connection status.
+ * Automatically binds to implementation of {@link SharedConnectivityService} specified in
+ * the device overlay when the first callback is registered.
* The {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} will be called if the
* registration failed.
*
@@ -284,9 +306,16 @@ public class SharedConnectivityManager {
SharedConnectivityCallbackProxy proxy =
new SharedConnectivityCallbackProxy(executor, callback);
if (mService == null) {
- synchronized (mCallbackProxyCache) {
+ boolean shouldBind;
+ synchronized (mProxyDataLock) {
+ // Size can be 1 in different cases of register/unregister sequences. If size is 0
+ // Bind never happened or unbind was called.
+ shouldBind = mCallbackProxyCache.size() == 0;
mCallbackProxyCache.put(callback, proxy);
}
+ if (shouldBind) {
+ bind();
+ }
return;
}
registerCallbackInternal(callback, proxy);
@@ -294,6 +323,7 @@ public class SharedConnectivityManager {
/**
* Unregisters a callback.
+ * Unbinds from {@link SharedConnectivityService} when no more callbacks are registered.
*
* @return Returns true if the callback was successfully unregistered, false otherwise.
*/
@@ -309,16 +339,27 @@ public class SharedConnectivityManager {
}
if (mService == null) {
- synchronized (mCallbackProxyCache) {
+ boolean shouldUnbind;
+ synchronized (mProxyDataLock) {
mCallbackProxyCache.remove(callback);
+ // Connection was never established, so all registered callbacks are in the cache.
+ shouldUnbind = mCallbackProxyCache.isEmpty();
+ }
+ if (shouldUnbind) {
+ unbind();
}
return true;
}
try {
- mService.unregisterCallback(mProxyMap.get(callback));
- synchronized (mProxyMap) {
+ boolean shouldUnbind;
+ synchronized (mProxyDataLock) {
+ mService.unregisterCallback(mProxyMap.get(callback));
mProxyMap.remove(callback);
+ shouldUnbind = mProxyMap.isEmpty();
+ }
+ if (shouldUnbind) {
+ unbind();
}
} catch (RemoteException e) {
Log.e(TAG, "Exception in unregisterCallback", e);
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index 96afe278e3e0..b585bd5cfd7b 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -28,15 +28,17 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.res.Resources;
import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
import android.os.Bundle;
-import android.os.Parcel;
import android.os.RemoteException;
import androidx.test.filters.SmallTest;
@@ -80,7 +82,7 @@ public class SharedConnectivityManagerTest {
@Mock
Executor mExecutor;
@Mock
- SharedConnectivityClientCallback mClientCallback;
+ SharedConnectivityClientCallback mClientCallback, mClientCallback2;
@Mock
Resources mResources;
@Mock
@@ -95,47 +97,52 @@ public class SharedConnectivityManagerTest {
setResources(mContext);
}
- /**
- * Verifies constructor is binding to service.
- */
@Test
- public void bindingToService() {
- SharedConnectivityManager.create(mContext);
+ public void resourcesNotDefined_createShouldReturnNull() {
+ when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
- verify(mContext).bindService(any(), any(), anyInt());
+ assertThat(SharedConnectivityManager.create(mContext)).isNull();
}
- /**
- * Verifies create method returns null when resources are not specified
- */
@Test
- public void resourcesNotDefined() {
- when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
+ public void bindingToServiceOnFirstCallbackRegistration() {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+ manager.registerCallback(mExecutor, mClientCallback);
- assertThat(SharedConnectivityManager.create(mContext)).isNull();
+ verify(mContext).bindService(any(Intent.class), any(ServiceConnection.class), anyInt());
}
- /**
- * Verifies registerCallback behavior.
- */
@Test
- public void registerCallback_serviceNotConnected_registrationCachedThenConnected()
- throws Exception {
+ public void bindIsCalledOnceOnMultipleCallbackRegistrations() throws Exception {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
manager.registerCallback(mExecutor, mClientCallback);
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
+ verify(mContext, times(1)).bindService(any(Intent.class), any(ServiceConnection.class),
+ anyInt());
+
+ manager.registerCallback(mExecutor, mClientCallback2);
+ verify(mContext, times(1)).bindService(any(Intent.class), any(ServiceConnection.class),
+ anyInt());
+ }
- // Since the binder is embedded in a proxy class, the call to registerCallback is done on
- // the proxy. So instead verifying that the proxy is calling the binder.
- verify(mIBinder).transact(anyInt(), any(Parcel.class), any(Parcel.class), anyInt());
+ @Test
+ public void unbindIsCalledOnLastCallbackUnregistrations() throws Exception {
+ SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
+ manager.registerCallback(mExecutor, mClientCallback);
+ manager.registerCallback(mExecutor, mClientCallback2);
+ manager.unregisterCallback(mClientCallback);
+ verify(mContext, never()).unbindService(
+ any(ServiceConnection.class));
+
+ manager.unregisterCallback(mClientCallback2);
+ verify(mContext, times(1)).unbindService(
+ any(ServiceConnection.class));
}
@Test
public void registerCallback_serviceNotConnected_canUnregisterAndReregister() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
manager.registerCallback(mExecutor, mClientCallback);
manager.unregisterCallback(mClientCallback);
@@ -177,9 +184,6 @@ public class SharedConnectivityManagerTest {
verify(mClientCallback).onRegisterCallbackFailed(any(RemoteException.class));
}
- /**
- * Verifies unregisterCallback behavior.
- */
@Test
public void unregisterCallback_withoutRegisteringFirst_serviceNotConnected_shouldFail() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
@@ -239,11 +243,8 @@ public class SharedConnectivityManagerTest {
assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
}
- /**
- * Verifies callback is called when service is connected
- */
@Test
- public void onServiceConnected_registerCallbackBeforeConnection() {
+ public void onServiceConnected() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.registerCallback(mExecutor, mClientCallback);
@@ -253,20 +254,7 @@ public class SharedConnectivityManagerTest {
}
@Test
- public void onServiceConnected_registerCallbackAfterConnection() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mClientCallback).onServiceConnected();
- }
-
- /**
- * Verifies callback is called when service is disconnected
- */
- @Test
- public void onServiceDisconnected_registerCallbackBeforeConnection() {
+ public void onServiceDisconnected() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
manager.registerCallback(mExecutor, mClientCallback);
@@ -276,20 +264,7 @@ public class SharedConnectivityManagerTest {
verify(mClientCallback).onServiceDisconnected();
}
- @Test
- public void onServiceDisconnected_registerCallbackAfterConnection() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
- manager.registerCallback(mExecutor, mClientCallback);
- manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
-
- verify(mClientCallback).onServiceDisconnected();
- }
- /**
- * Verifies connectHotspotNetwork behavior.
- */
@Test
public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
HotspotNetwork network = buildHotspotNetwork();
@@ -320,9 +295,6 @@ public class SharedConnectivityManagerTest {
assertThat(manager.connectHotspotNetwork(network)).isFalse();
}
- /**
- * Verifies disconnectHotspotNetwork behavior.
- */
@Test
public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
HotspotNetwork network = buildHotspotNetwork();
@@ -353,9 +325,6 @@ public class SharedConnectivityManagerTest {
assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
}
- /**
- * Verifies connectKnownNetwork behavior.
- */
@Test
public void connectKnownNetwork_serviceNotConnected_shouldFail() throws RemoteException {
KnownNetwork network = buildKnownNetwork();
@@ -386,9 +355,6 @@ public class SharedConnectivityManagerTest {
assertThat(manager.connectKnownNetwork(network)).isFalse();
}
- /**
- * Verifies forgetKnownNetwork behavior.
- */
@Test
public void forgetKnownNetwork_serviceNotConnected_shouldFail() {
KnownNetwork network = buildKnownNetwork();
@@ -419,9 +385,6 @@ public class SharedConnectivityManagerTest {
assertThat(manager.forgetKnownNetwork(network)).isFalse();
}
- /**
- * Verify getters.
- */
@Test
public void getHotspotNetworks_serviceNotConnected_shouldReturnNull() {
SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);