summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java1
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java52
-rw-r--r--services/core/java/com/android/server/wm/ActivityInterceptorCallback.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java18
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java3
7 files changed, 58 insertions, 37 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 326a5f2582e1..9af5b667fc44 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -264,7 +264,6 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 11cb5a7167dc..e8546a768429 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -17,6 +17,7 @@
package com.android.server.policy;
import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
@@ -58,8 +59,6 @@ import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -93,6 +92,7 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityInterceptorCallback;
+import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.ArrayList;
@@ -115,7 +115,6 @@ public final class PermissionPolicyService extends SystemService {
private static final String SYSTEM_PKG = "android";
private static final boolean DEBUG = false;
private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 60000;
- private static final long ACTIVITY_START_DELAY_MS = 200;
private final Object mLock = new Object();
@@ -155,8 +154,7 @@ public final class PermissionPolicyService extends SystemService {
private List<String> mAppOpPermissions;
- private final Context mContext;
- private final Handler mHandler;
+ private Context mContext;
private PackageManagerInternal mPackageManagerInternal;
private PermissionManagerServiceInternal mPermissionManagerInternal;
private NotificationManagerInternal mNotificationManager;
@@ -167,7 +165,6 @@ public final class PermissionPolicyService extends SystemService {
super(context);
mContext = context;
- mHandler = new Handler(Looper.getMainLooper());
mPackageManager = context.getPackageManager();
mKeyguardManager = context.getSystemService(KeyguardManager.class);
LocalServices.addService(PermissionPolicyInternal.class, new Internal());
@@ -1072,7 +1069,7 @@ public final class PermissionPolicyService extends SystemService {
clearNotificationReviewFlagsIfNeeded(activityInfo.packageName, user);
} else {
showNotificationPromptIfNeeded(activityInfo.packageName,
- taskInfo.userId, taskInfo.taskId);
+ taskInfo.userId, taskInfo.taskId, info);
}
}
};
@@ -1103,15 +1100,21 @@ public final class PermissionPolicyService extends SystemService {
return true;
}
+ @Override
public void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
int taskId) {
+ showNotificationPromptIfNeeded(packageName, userId, taskId, null /* info */);
+ }
+
+ void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
+ int taskId, @Nullable ActivityInterceptorInfo info) {
UserHandle user = UserHandle.of(userId);
if (packageName == null || taskId == ActivityTaskManager.INVALID_TASK_ID
|| !shouldForceShowNotificationPermissionRequest(packageName, user)) {
return;
}
- launchNotificationPermissionRequestDialog(packageName, user, taskId);
+ launchNotificationPermissionRequestDialog(packageName, user, taskId, info);
}
@Override
@@ -1180,7 +1183,7 @@ public final class PermissionPolicyService extends SystemService {
}
private void launchNotificationPermissionRequestDialog(String pkgName, UserHandle user,
- int taskId) {
+ int taskId, @Nullable ActivityInterceptorInfo info) {
Intent grantPermission = mPackageManager
.buildRequestPermissionsIntent(new String[] { POST_NOTIFICATIONS });
// Prevent the front-most activity entering pip due to overlay activity started on top.
@@ -1189,18 +1192,29 @@ public final class PermissionPolicyService extends SystemService {
ACTION_REQUEST_PERMISSIONS_FOR_OTHER);
grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName);
- ActivityOptions options = new ActivityOptions(new Bundle());
+ final boolean remoteAnimation = info != null && info.checkedOptions != null
+ && info.checkedOptions.getAnimationType() == ANIM_REMOTE_ANIMATION
+ && info.clearOptionsAnimation != null;
+ ActivityOptions options = remoteAnimation ? ActivityOptions.makeRemoteAnimation(
+ info.checkedOptions.getRemoteAnimationAdapter(),
+ info.checkedOptions.getRemoteTransition())
+ : new ActivityOptions(new Bundle());
options.setTaskOverlay(true, false);
options.setLaunchTaskId(taskId);
- mHandler.postDelayed(() -> {
- try {
- mContext.startActivityAsUser(
- grantPermission, options.toBundle(), user);
- } catch (Exception e) {
- Log.e(LOG_TAG, "couldn't start grant permission dialog"
- + "for other package " + pkgName, e);
- }
- }, ACTIVITY_START_DELAY_MS);
+ if (remoteAnimation) {
+ // Remote animation set on the intercepted activity will be handled by the grant
+ // permission activity, which is launched below. So we need to clear remote
+ // animation from the intercepted activity and its siblings to prevent duplication.
+ // This should trigger ActivityRecord#clearOptionsAnimationForSiblings for the
+ // intercepted activity.
+ info.clearOptionsAnimation.run();
+ }
+ try {
+ mContext.startActivityAsUser(grantPermission, options.toBundle(), user);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "couldn't start grant permission dialog"
+ + "for other package " + pkgName, e);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
index 1d65cbb70ffe..d2053fa25ad8 100644
--- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
+++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
@@ -108,11 +108,13 @@ public abstract class ActivityInterceptorCallback {
public final int callingPid;
public final int callingUid;
public final ActivityOptions checkedOptions;
+ public final @Nullable Runnable clearOptionsAnimation;
public ActivityInterceptorInfo(int realCallingUid, int realCallingPid, int userId,
String callingPackage, String callingFeatureId, Intent intent,
ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, int callingPid,
- int callingUid, ActivityOptions checkedOptions) {
+ int callingUid, ActivityOptions checkedOptions,
+ @Nullable Runnable clearOptionsAnimation) {
this.realCallingUid = realCallingUid;
this.realCallingPid = realCallingPid;
this.userId = userId;
@@ -125,6 +127,7 @@ public abstract class ActivityInterceptorCallback {
this.callingPid = callingPid;
this.callingUid = callingUid;
this.checkedOptions = checkedOptions;
+ this.clearOptionsAnimation = clearOptionsAnimation;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0b52fd643a1c..d8ad2a57afa4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4592,14 +4592,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
applyOptionsAnimation(mPendingOptions, intent);
}
- if (task == null) {
- clearOptionsAnimation();
- } else {
- // This will clear the options for all the ActivityRecords for this Task.
- task.forAllActivities((r) -> {
- r.clearOptionsAnimation();
- });
- }
+ clearOptionsAnimationForSiblings();
}
/**
@@ -4786,6 +4779,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mPendingRemoteTransition = null;
}
+ void clearOptionsAnimationForSiblings() {
+ if (task == null) {
+ clearOptionsAnimation();
+ } else {
+ // This will clear the options for all the ActivityRecords for this Task.
+ task.forAllActivities(ActivityRecord::clearOptionsAnimation);
+ }
+ }
+
ActivityOptions getOptions() {
return mPendingOptions;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index cdeb86c3ee77..a452013bf42a 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -188,7 +188,7 @@ class ActivityStartInterceptor {
final SparseArray<ActivityInterceptorCallback> callbacks =
mService.getActivityInterceptorCallbacks();
final ActivityInterceptorCallback.ActivityInterceptorInfo interceptorInfo =
- getInterceptorInfo();
+ getInterceptorInfo(null /* clearOptionsAnimation */);
for (int i = 0; i < callbacks.size(); i++) {
final ActivityInterceptorCallback callback = callbacks.valueAt(i);
@@ -406,20 +406,22 @@ class ActivityStartInterceptor {
/**
* Called when an activity is successfully launched.
*/
- void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo) {
+ void onActivityLaunched(TaskInfo taskInfo, ActivityRecord r) {
final SparseArray<ActivityInterceptorCallback> callbacks =
mService.getActivityInterceptorCallbacks();
- ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo();
+ ActivityInterceptorCallback.ActivityInterceptorInfo info = getInterceptorInfo(
+ r::clearOptionsAnimationForSiblings);
for (int i = 0; i < callbacks.size(); i++) {
final ActivityInterceptorCallback callback = callbacks.valueAt(i);
- callback.onActivityLaunched(taskInfo, activityInfo, info);
+ callback.onActivityLaunched(taskInfo, r.info, info);
}
}
- private ActivityInterceptorCallback.ActivityInterceptorInfo getInterceptorInfo() {
+ private ActivityInterceptorCallback.ActivityInterceptorInfo getInterceptorInfo(
+ @Nullable Runnable clearOptionsAnimation) {
return new ActivityInterceptorCallback.ActivityInterceptorInfo(mRealCallingUid,
mRealCallingPid, mUserId, mCallingPackage, mCallingFeatureId, mIntent,
mRInfo, mAInfo, mResolvedType, mCallingPid, mCallingUid,
- mActivityOptions);
+ mActivityOptions, clearOptionsAnimation);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0b717540a7a6..003268b33cdc 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1585,7 +1585,7 @@ class ActivityStarter {
}
if (ActivityManager.isStartResultSuccessful(result)) {
- mInterceptor.onActivityLaunched(targetTask.getTaskInfo(), r.info);
+ mInterceptor.onActivityLaunched(targetTask.getTaskInfo(), r);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 24ff3f96100a..73e409abf0c1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -31,6 +31,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.mock;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
@@ -350,7 +351,7 @@ public class ActivityStartInterceptorTest {
assertEquals(1, mActivityInterceptorCallbacks.size());
final ActivityInterceptorCallback callback = mActivityInterceptorCallbacks.valueAt(0);
spyOn(callback);
- mInterceptor.onActivityLaunched(null, null);
+ mInterceptor.onActivityLaunched(null, mock(ActivityRecord.class));
verify(callback, times(1)).onActivityLaunched(any(), any(), any());
}