Merge changes Id6161f92,Ie0d8849a into rvc-dev

* changes:
  Introduce security checks to startDreamActivity
  Add verification for setting ACTIVITY_TYPE_DREAM
This commit is contained in:
Galia Peycheva
2020-04-01 10:18:19 +00:00
committed by Android (Google) Code Review
8 changed files with 115 additions and 49 deletions

View File

@@ -49,6 +49,12 @@ public abstract class DreamManagerInternal {
* Called by the ActivityTaskManagerService to verify that the startDreamActivity * Called by the ActivityTaskManagerService to verify that the startDreamActivity
* request comes from the current active dream component. * request comes from the current active dream component.
* *
* This function and its call path should not acquire the DreamManagerService lock
* to avoid deadlock with the ActivityTaskManager lock.
*
* TODO: Make this interaction push-based - the DreamManager should inform the
* ActivityTaskManager whenever the active dream component changes.
*
* @param doze If true returns the current active doze component. Otherwise, returns the * @param doze If true returns the current active doze component. Otherwise, returns the
* active dream component. * active dream component.
*/ */

View File

@@ -1054,6 +1054,7 @@ public class DreamService extends Service implements Window.Callback {
// DreamServiceWrapper.onActivityCreated. // DreamServiceWrapper.onActivityCreated.
if (!mWindowless) { if (!mWindowless) {
Intent i = new Intent(this, DreamActivity.class); Intent i = new Intent(this, DreamActivity.class);
i.setPackage(getApplicationContext().getPackageName());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper); i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);

View File

@@ -51,6 +51,7 @@ import com.android.internal.util.DumpUtils;
import com.android.server.FgThread; import com.android.server.FgThread;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.SystemService; import com.android.server.SystemService;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -75,6 +76,7 @@ public final class DreamManagerService extends SystemService {
private final PowerManager mPowerManager; private final PowerManager mPowerManager;
private final PowerManagerInternal mPowerManagerInternal; private final PowerManagerInternal mPowerManagerInternal;
private final PowerManager.WakeLock mDozeWakeLock; private final PowerManager.WakeLock mDozeWakeLock;
private final ActivityTaskManagerInternal mAtmInternal;
private Binder mCurrentDreamToken; private Binder mCurrentDreamToken;
private ComponentName mCurrentDreamName; private ComponentName mCurrentDreamName;
@@ -97,6 +99,7 @@ public final class DreamManagerService extends SystemService {
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mPowerManagerInternal = getLocalService(PowerManagerInternal.class); mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG); mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
mDozeConfig = new AmbientDisplayConfiguration(mContext); mDozeConfig = new AmbientDisplayConfiguration(mContext);
} }
@@ -383,8 +386,10 @@ public final class DreamManagerService extends SystemService {
PowerManager.WakeLock wakeLock = mPowerManager PowerManager.WakeLock wakeLock = mPowerManager
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream"); .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
mHandler.post(wakeLock.wrap( mHandler.post(wakeLock.wrap(() -> {
() -> mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock))); mAtmInternal.notifyDreamStateChanged(true);
mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
}));
} }
private void stopDreamLocked(final boolean immediate) { private void stopDreamLocked(final boolean immediate) {
@@ -422,6 +427,7 @@ public final class DreamManagerService extends SystemService {
} }
mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN; mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT; mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
mAtmInternal.notifyDreamStateChanged(false);
} }
private void checkPermission(String permission) { private void checkPermission(String permission) {

View File

@@ -36,6 +36,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE; import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
import static android.app.WaitResult.INVALID_DELAY; import static android.app.WaitResult.INVALID_DELAY;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -269,6 +270,8 @@ import android.os.SystemClock;
import android.os.Trace; import android.os.Trace;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession; import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.EventLog; import android.util.EventLog;
@@ -2035,6 +2038,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return false; return false;
} }
static boolean canLaunchDreamActivity(String packageName) {
final DreamManagerInternal dreamManager =
LocalServices.getService(DreamManagerInternal.class);
// Verify that the package is the current active dream. The getActiveDreamComponent()
// call path does not acquire the DreamManager lock and thus is safe to use.
final ComponentName activeDream = dreamManager.getActiveDreamComponent(false /* doze */);
if (activeDream == null || activeDream.getPackageName() == null
|| !activeDream.getPackageName().equals(packageName)) {
return false;
}
// Verify that the device is dreaming.
if (!LocalServices.getService(ActivityTaskManagerInternal.class).isDreaming()) {
return false;
}
return true;
}
private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
ActivityOptions options, ActivityRecord sourceRecord) { ActivityOptions options, ActivityRecord sourceRecord) {
int activityType = ACTIVITY_TYPE_UNDEFINED; int activityType = ACTIVITY_TYPE_UNDEFINED;
@@ -2054,6 +2077,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
&& canLaunchAssistActivity(launchedFromPackage)) { && canLaunchAssistActivity(launchedFromPackage)) {
activityType = ACTIVITY_TYPE_ASSISTANT; activityType = ACTIVITY_TYPE_ASSISTANT;
} else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_DREAM
&& canLaunchDreamActivity(launchedFromPackage)
&& DreamActivity.class.getName() == info.name) {
activityType = ACTIVITY_TYPE_DREAM;
} }
setActivityType(activityType); setActivityType(activityType);
} }

View File

@@ -341,7 +341,6 @@ class ActivityStarter {
int filterCallingUid; int filterCallingUid;
PendingIntentRecord originatingPendingIntent; PendingIntentRecord originatingPendingIntent;
boolean allowBackgroundActivityStart; boolean allowBackgroundActivityStart;
boolean isDream;
/** /**
* If set to {@code true}, allows this activity start to look into * If set to {@code true}, allows this activity start to look into
@@ -393,7 +392,6 @@ class ActivityStarter {
filterCallingUid = UserHandle.USER_NULL; filterCallingUid = UserHandle.USER_NULL;
originatingPendingIntent = null; originatingPendingIntent = null;
allowBackgroundActivityStart = false; allowBackgroundActivityStart = false;
isDream = false;
} }
/** /**
@@ -434,7 +432,6 @@ class ActivityStarter {
filterCallingUid = request.filterCallingUid; filterCallingUid = request.filterCallingUid;
originatingPendingIntent = request.originatingPendingIntent; originatingPendingIntent = request.originatingPendingIntent;
allowBackgroundActivityStart = request.allowBackgroundActivityStart; allowBackgroundActivityStart = request.allowBackgroundActivityStart;
isDream = request.isDream;
} }
/** /**
@@ -985,7 +982,7 @@ class ActivityStarter {
restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid, restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp, callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
request.originatingPendingIntent, request.allowBackgroundActivityStart, request.originatingPendingIntent, request.allowBackgroundActivityStart,
request.isDream, intent); intent);
} finally { } finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
} }
@@ -1195,7 +1192,7 @@ class ActivityStarter {
boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid, boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
final String callingPackage, int realCallingUid, int realCallingPid, final String callingPackage, int realCallingUid, int realCallingPid,
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart, boolean isDream, Intent intent) { boolean allowBackgroundActivityStart, Intent intent) {
// don't abort for the most important UIDs // don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(callingUid); final int callingAppId = UserHandle.getAppId(callingUid);
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
@@ -1203,10 +1200,6 @@ class ActivityStarter {
return false; return false;
} }
// don't abort if this is the dream activity
if (isDream) {
return false;
}
// don't abort if the callingUid has a visible window or is a persistent system process // don't abort if the callingUid has a visible window or is a persistent system process
final int callingUidProcState = mService.getUidState(callingUid); final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow = final boolean callingUidHasAnyVisibleWindow =
@@ -2717,11 +2710,6 @@ class ActivityStarter {
return this; return this;
} }
ActivityStarter setIsDream(boolean isDream) {
mRequest.isDream = isDream;
return this;
}
void dump(PrintWriter pw, String prefix) { void dump(PrintWriter pw, String prefix) {
prefix = prefix + " "; prefix = prefix + " ";
pw.print(prefix); pw.print(prefix);

View File

@@ -289,6 +289,11 @@ public abstract class ActivityTaskManagerInternal {
*/ */
public abstract void notifyActiveVoiceInteractionServiceChanged(ComponentName component); public abstract void notifyActiveVoiceInteractionServiceChanged(ComponentName component);
/**
* Called when the device changes its dreaming state.
*/
public abstract void notifyDreamStateChanged(boolean dreaming);
/** /**
* Set a uid that is allowed to bypass stopped app switches, launching an app * Set a uid that is allowed to bypass stopped app switches, launching an app
* whenever it wants. * whenever it wants.
@@ -318,6 +323,7 @@ public abstract class ActivityTaskManagerInternal {
public abstract void clearHeavyWeightProcessIfEquals(WindowProcessController proc); public abstract void clearHeavyWeightProcessIfEquals(WindowProcessController proc);
public abstract void finishHeavyWeightApp(); public abstract void finishHeavyWeightApp();
public abstract boolean isDreaming();
public abstract boolean isSleeping(); public abstract boolean isSleeping();
public abstract boolean isShuttingDown(); public abstract boolean isShuttingDown();
public abstract boolean shuttingDown(boolean booted, int timeout); public abstract boolean shuttingDown(boolean booted, int timeout);

View File

@@ -212,7 +212,6 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.provider.Settings; import android.provider.Settings;
import android.service.dreams.DreamActivity; import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession; import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal; import android.service.voice.VoiceInteractionManagerInternal;
import android.sysprop.DisplayProperties; import android.sysprop.DisplayProperties;
@@ -598,6 +597,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/ */
private boolean mSleeping = false; private boolean mSleeping = false;
/**
* The mDreaming state is set by the {@link DreamManagerService} when it receives a request to
* start/stop the dream. It is set to true shortly before the {@link DreamService} is started.
* It is set to false after the {@link DreamService} is stopped.
*/
private boolean mDreaming = false;
/** /**
* The process state used for processes that are running the top activities. * The process state used for processes that are running the top activities.
* This changes between TOP and TOP_SLEEPING to following mSleeping. * This changes between TOP and TOP_SLEEPING to following mSleeping.
@@ -1238,36 +1244,29 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
} }
} }
@Override private void enforceCallerIsDream(String callerPackageName) {
public boolean startDreamActivity(Intent intent) {
final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
final long origId = Binder.clearCallingIdentity(); final long origId = Binder.clearCallingIdentity();
try {
// The dream activity is only called for non-doze dreams. if (!ActivityRecord.canLaunchDreamActivity(callerPackageName)) {
final ComponentName currentDream = LocalServices.getService(DreamManagerInternal.class) throw new SecurityException("The dream activity can be started only when the device"
.getActiveDreamComponent(/* doze= */ false); + " is dreaming and only by the active dream package.");
}
if (currentDream == null || currentDream.getPackageName() == null } finally {
|| !currentDream.getPackageName().equals(process.mInfo.packageName)) { Binder.restoreCallingIdentity(origId);
Slog.e(TAG, "Calling package is not the current dream package. "
+ "Aborting startDreamActivity...");
return false;
} }
}
@Override
public boolean startDreamActivity(@NonNull Intent intent) {
assertPackageMatchesCallingUid(intent.getPackage());
enforceCallerIsDream(intent.getPackage());
final ActivityInfo a = new ActivityInfo(); final ActivityInfo a = new ActivityInfo();
a.theme = com.android.internal.R.style.Theme_Dream; a.theme = com.android.internal.R.style.Theme_Dream;
a.exported = true; a.exported = true;
a.name = DreamActivity.class.getName(); a.name = DreamActivity.class.getName();
a.packageName = process.mInfo.packageName;
a.applicationInfo = process.mInfo;
a.processName = process.mInfo.processName;
a.uiOptions = process.mInfo.uiOptions;
a.taskAffinity = "android:" + a.packageName + "/dream";
a.enabled = true; a.enabled = true;
a.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE; a.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE;
a.persistableMode = ActivityInfo.PERSIST_NEVER; a.persistableMode = ActivityInfo.PERSIST_NEVER;
a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
@@ -1276,15 +1275,34 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityOptions options = ActivityOptions.makeBasic(); final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM); options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
try { synchronized (mGlobalLock) {
getActivityStartController().obtainStarter(intent, "dream") final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
.setActivityInfo(a)
.setActivityOptions(options.toBundle()) a.packageName = process.mInfo.packageName;
.setIsDream(true) a.applicationInfo = process.mInfo;
.execute(); a.processName = process.mInfo.processName;
return true; a.uiOptions = process.mInfo.uiOptions;
} finally { a.taskAffinity = "android:" + a.packageName + "/dream";
Binder.restoreCallingIdentity(origId);
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
try {
getActivityStartController().obtainStarter(intent, "dream")
.setCallingUid(callingUid)
.setCallingPid(callingPid)
.setActivityInfo(a)
.setActivityOptions(options.toBundle())
// 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())
.setAllowBackgroundActivityStart(true)
.execute();
return true;
} finally {
Binder.restoreCallingIdentity(origId);
}
} }
} }
@@ -2476,7 +2494,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityStarter starter = getActivityStartController().obtainStarter( final ActivityStarter starter = getActivityStartController().obtainStarter(
null /* intent */, "moveTaskToFront"); null /* intent */, "moveTaskToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1, if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
-1, callerApp, null, false, false, null)) { -1, callerApp, null, false, null)) {
if (!isBackgroundActivityStartsEnabled()) { if (!isBackgroundActivityStartsEnabled()) {
return; return;
} }
@@ -6336,6 +6354,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
} }
} }
@Override
public void notifyDreamStateChanged(boolean dreaming) {
synchronized (mGlobalLock) {
mDreaming = dreaming;
}
}
@Override @Override
public void setAllowAppSwitches(@NonNull String type, int uid, int userId) { public void setAllowAppSwitches(@NonNull String type, int uid, int userId) {
if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_OR_STOPPED)) { if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_OR_STOPPED)) {
@@ -6438,6 +6463,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
} }
} }
@Override
public boolean isDreaming() {
synchronized (mGlobalLock) {
return mDreaming;
}
}
@HotPath(caller = HotPath.OOM_ADJUSTMENT) @HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override @Override
public boolean isSleeping() { public boolean isSleeping() {

View File

@@ -111,7 +111,7 @@ class AppTaskImpl extends IAppTask.Stub {
final ActivityStarter starter = mService.getActivityStartController().obtainStarter( final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
null /* intent */, "moveToFront"); null /* intent */, "moveToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
callingPackage, -1, -1, callerApp, null, false, false, null)) { callingPackage, -1, -1, callerApp, null, false, null)) {
if (!mService.isBackgroundActivityStartsEnabled()) { if (!mService.isBackgroundActivityStartsEnabled()) {
return; return;
} }