Merge "Do not kill dream process when stopping dream" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0a5435a553
@@ -24,7 +24,6 @@ import android.app.GrantedUriPermission;
|
||||
import android.app.IApplicationThread;
|
||||
import android.app.IActivityClientController;
|
||||
import android.app.IActivityController;
|
||||
import android.app.IAppTask;
|
||||
import android.app.IAssistDataReceiver;
|
||||
import android.app.IInstrumentationWatcher;
|
||||
import android.app.IProcessObserver;
|
||||
@@ -107,14 +106,6 @@ interface IActivityTaskManager {
|
||||
in ProfilerInfo profilerInfo, in Bundle options, int userId);
|
||||
boolean startNextMatchingActivity(in IBinder callingActivity,
|
||||
in Intent intent, in Bundle options);
|
||||
|
||||
/**
|
||||
* The DreamActivity has to be started in a special way that does not involve the PackageParser.
|
||||
* The DreamActivity is a framework component inserted in the dream application process. Hence,
|
||||
* it is not declared in the application's manifest and cannot be parsed. startDreamActivity
|
||||
* creates the activity and starts it without reaching out to the PackageParser.
|
||||
*/
|
||||
boolean startDreamActivity(in Intent intent);
|
||||
int startActivityIntentSender(in IApplicationThread caller,
|
||||
in IIntentSender target, in IBinder whitelistToken, in Intent fillInIntent,
|
||||
in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Service;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
@@ -1268,9 +1267,7 @@ public class DreamService extends Service implements Window.Callback {
|
||||
fetchDreamLabel(this, serviceInfo, isPreviewMode));
|
||||
|
||||
try {
|
||||
if (!ActivityTaskManager.getService().startDreamActivity(i)) {
|
||||
detach();
|
||||
}
|
||||
mDreamManager.startDreamActivity(i);
|
||||
} catch (SecurityException e) {
|
||||
Log.w(mTag,
|
||||
"Received SecurityException trying to start DreamActivity. "
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.service.dreams;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.IBinder;
|
||||
@@ -45,4 +46,5 @@ interface IDreamManager {
|
||||
void setDreamComponentsForUser(int userId, in ComponentName[] componentNames);
|
||||
void setSystemDreamComponent(in ComponentName componentName);
|
||||
void registerDreamOverlayService(in ComponentName componentName);
|
||||
void startDreamActivity(in Intent intent);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
package com.android.server.dreams;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
|
||||
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
|
||||
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.BroadcastOptions;
|
||||
import android.app.IAppTask;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -213,6 +213,27 @@ final class DreamController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an appTask for the dream with token {@code dreamToken}, so that the dream controller
|
||||
* can stop the dream task when necessary.
|
||||
*/
|
||||
void setDreamAppTask(Binder dreamToken, IAppTask appTask) {
|
||||
if (mCurrentDream == null || mCurrentDream.mToken != dreamToken
|
||||
|| mCurrentDream.mAppTask != null) {
|
||||
Slog.e(TAG, "Illegal dream activity start. mCurrentDream.mToken = "
|
||||
+ mCurrentDream.mToken + ", illegal dreamToken = " + dreamToken
|
||||
+ ". Ending this dream activity.");
|
||||
try {
|
||||
appTask.finishAndRemoveTask();
|
||||
} catch (RemoteException | RuntimeException e) {
|
||||
Slog.e(TAG, "Unable to stop illegal dream activity.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mCurrentDream.mAppTask = appTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops dreaming.
|
||||
*
|
||||
@@ -303,8 +324,14 @@ final class DreamController {
|
||||
mSentStartBroadcast = false;
|
||||
}
|
||||
|
||||
mActivityTaskManager.removeRootTasksWithActivityTypes(
|
||||
new int[] {ACTIVITY_TYPE_DREAM});
|
||||
if (mCurrentDream != null && mCurrentDream.mAppTask != null) {
|
||||
// Finish the dream task in case it hasn't finished by itself already.
|
||||
try {
|
||||
mCurrentDream.mAppTask.finishAndRemoveTask();
|
||||
} catch (RemoteException | RuntimeException e) {
|
||||
Slog.e(TAG, "Unable to stop dream activity.");
|
||||
}
|
||||
}
|
||||
|
||||
mListener.onDreamStopped(dream.mToken);
|
||||
}
|
||||
@@ -364,6 +391,7 @@ final class DreamController {
|
||||
public final boolean mIsPreviewMode;
|
||||
public final boolean mCanDoze;
|
||||
public final int mUserId;
|
||||
public IAppTask mAppTask;
|
||||
|
||||
public PowerManager.WakeLock mWakeLock;
|
||||
public boolean mBound;
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IAppTask;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@@ -37,6 +38,7 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.display.AmbientDisplayConfiguration;
|
||||
@@ -116,6 +118,7 @@ public final class DreamManagerService extends SystemService {
|
||||
private final PowerManagerInternal mPowerManagerInternal;
|
||||
private final PowerManager.WakeLock mDozeWakeLock;
|
||||
private final ActivityTaskManagerInternal mAtmInternal;
|
||||
private final PackageManagerInternal mPmInternal;
|
||||
private final UserManager mUserManager;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final DreamUiEventLogger mDreamUiEventLogger;
|
||||
@@ -216,6 +219,7 @@ public final class DreamManagerService extends SystemService {
|
||||
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
||||
mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
|
||||
mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
|
||||
mPmInternal = getLocalService(PackageManagerInternal.class);
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, DOZE_WAKE_LOCK_TAG);
|
||||
mDozeConfig = new AmbientDisplayConfiguration(mContext);
|
||||
@@ -1064,6 +1068,64 @@ public final class DreamManagerService extends SystemService {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void startDreamActivity(@NonNull Intent intent) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
// We post here, because startDreamActivity and setDreamAppTask have to run
|
||||
// synchronously and DreamController#setDreamAppTask has to run on mHandler.
|
||||
mHandler.post(() -> {
|
||||
final Binder dreamToken;
|
||||
final String dreamPackageName;
|
||||
synchronized (mLock) {
|
||||
if (mCurrentDream == null) {
|
||||
Slog.e(TAG, "Attempt to start DreamActivity, but the device is not "
|
||||
+ "dreaming. Aborting without starting the DreamActivity.");
|
||||
return;
|
||||
}
|
||||
dreamToken = mCurrentDream.token;
|
||||
dreamPackageName = mCurrentDream.name.getPackageName();
|
||||
}
|
||||
|
||||
if (!canLaunchDreamActivity(dreamPackageName, intent.getPackage(),
|
||||
callingUid)) {
|
||||
Slog.e(TAG, "The dream activity can be started only when the device is dreaming"
|
||||
+ " and only by the active dream package.");
|
||||
return;
|
||||
}
|
||||
|
||||
final IAppTask appTask = mAtmInternal.startDreamActivity(intent, callingUid,
|
||||
callingPid);
|
||||
if (appTask == null) {
|
||||
Slog.e(TAG, "Could not start dream activity.");
|
||||
stopDreamInternal(true, "DreamActivity not started");
|
||||
return;
|
||||
}
|
||||
mController.setDreamAppTask(dreamToken, appTask);
|
||||
});
|
||||
}
|
||||
|
||||
boolean canLaunchDreamActivity(String dreamPackageName, String packageName,
|
||||
int callingUid) {
|
||||
if (dreamPackageName == null || packageName == null) {
|
||||
Slog.e(TAG, "Cannot launch dream activity due to invalid state. dream component= "
|
||||
+ dreamPackageName + ", packageName=" + packageName);
|
||||
return false;
|
||||
}
|
||||
if (!mPmInternal.isSameApp(packageName, callingUid, UserHandle.getUserId(callingUid))) {
|
||||
Slog.e(TAG, "Cannot launch dream activity because package="
|
||||
+ packageName + " does not match callingUid=" + callingUid);
|
||||
return false;
|
||||
}
|
||||
if (packageName.equals(dreamPackageName)) {
|
||||
return true;
|
||||
}
|
||||
Slog.e(TAG, "Dream packageName does not match active dream. Package " + packageName
|
||||
+ " does not match " + dreamPackageName);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class LocalService extends DreamManagerInternal {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.app.ActivityManager;
|
||||
import android.app.AppProtoEnums;
|
||||
import android.app.BackgroundStartPrivileges;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.IAppTask;
|
||||
import android.app.IApplicationThread;
|
||||
import android.app.ITaskStackListener;
|
||||
import android.app.ProfilerInfo;
|
||||
@@ -307,6 +308,12 @@ public abstract class ActivityTaskManagerInternal {
|
||||
*/
|
||||
public abstract void notifyActiveDreamChanged(@Nullable ComponentName activeDreamComponent);
|
||||
|
||||
/**
|
||||
* Starts a dream activity in the DreamService's process.
|
||||
*/
|
||||
public abstract IAppTask startDreamActivity(@NonNull Intent intent, int callingUid,
|
||||
int callingPid);
|
||||
|
||||
/**
|
||||
* Set a uid that is allowed to bypass stopped app switches, launching an app
|
||||
* whenever it wants.
|
||||
|
||||
@@ -1467,23 +1467,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void enforceCallerIsDream(String callerPackageName) {
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!canLaunchDreamActivity(callerPackageName)) {
|
||||
throw new SecurityException("The dream activity can be started only when the device"
|
||||
+ " is dreaming and only by the active dream package.");
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startDreamActivity(@NonNull Intent intent) {
|
||||
assertPackageMatchesCallingUid(intent.getPackage());
|
||||
enforceCallerIsDream(intent.getPackage());
|
||||
|
||||
private IAppTask startDreamActivityInternal(@NonNull Intent intent, int callingUid,
|
||||
int callingPid) {
|
||||
final ActivityInfo a = new ActivityInfo();
|
||||
a.theme = com.android.internal.R.style.Theme_Dream;
|
||||
a.exported = true;
|
||||
@@ -1501,7 +1486,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
|
||||
final WindowProcessController process = mProcessMap.getProcess(callingPid);
|
||||
|
||||
a.packageName = process.mInfo.packageName;
|
||||
a.applicationInfo = process.mInfo;
|
||||
@@ -1509,26 +1494,25 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
a.uiOptions = process.mInfo.uiOptions;
|
||||
a.taskAffinity = "android:" + a.packageName + "/dream";
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
getActivityStartController().obtainStarter(intent, "dream")
|
||||
.setCallingUid(callingUid)
|
||||
.setCallingPid(callingPid)
|
||||
.setCallingPackage(intent.getPackage())
|
||||
.setActivityInfo(a)
|
||||
.setActivityOptions(createSafeActivityOptionsWithBalAllowed(options))
|
||||
// To start the dream from background, we need to start it from a persistent
|
||||
// system process. Here we set the real calling uid to the system server uid
|
||||
.setRealCallingUid(Binder.getCallingUid())
|
||||
.setBackgroundStartPrivileges(BackgroundStartPrivileges.ALLOW_BAL)
|
||||
.execute();
|
||||
return true;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
}
|
||||
final ActivityRecord[] outActivity = new ActivityRecord[1];
|
||||
getActivityStartController().obtainStarter(intent, "dream")
|
||||
.setCallingUid(callingUid)
|
||||
.setCallingPid(callingPid)
|
||||
.setCallingPackage(intent.getPackage())
|
||||
.setActivityInfo(a)
|
||||
.setActivityOptions(createSafeActivityOptionsWithBalAllowed(options))
|
||||
.setOutActivity(outActivity)
|
||||
// To start the dream from background, we need to start it from a persistent
|
||||
// system process. Here we set the real calling uid to the system server uid
|
||||
.setRealCallingUid(Binder.getCallingUid())
|
||||
.setBackgroundStartPrivileges(BackgroundStartPrivileges.ALLOW_BAL)
|
||||
.execute();
|
||||
|
||||
final ActivityRecord started = outActivity[0];
|
||||
final IAppTask appTask = started == null ? null :
|
||||
new AppTaskImpl(this, started.getTask().mTaskId, callingUid);
|
||||
return appTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5925,6 +5909,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAppTask startDreamActivity(@NonNull Intent intent, int callingUid, int callingPid) {
|
||||
return startDreamActivityInternal(intent, callingUid, callingPid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowAppSwitches(@NonNull String type, int uid, int userId) {
|
||||
if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_OR_STOPPED)) {
|
||||
|
||||
Reference in New Issue
Block a user