summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Galia Peycheva <galinap@google.com> 2020-04-01 10:18:19 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-04-01 10:18:19 +0000
commit5a0549cd42a01352473d42ab39ed8458d47e9cce (patch)
tree5b08c6619d23f9a94300417a6b9bc2b9298ad277
parentd7df0c13d93d0a0fb8a486a946e5370ae4c5ff21 (diff)
parented401cc16d27d90c78b9744b580f00529e391e9a (diff)
Merge changes Id6161f92,Ie0d8849a into rvc-dev
* changes: Introduce security checks to startDreamActivity Add verification for setting ACTIVITY_TYPE_DREAM
-rw-r--r--core/java/android/service/dreams/DreamManagerInternal.java6
-rw-r--r--core/java/android/service/dreams/DreamService.java1
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java10
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java27
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java96
-rw-r--r--services/core/java/com/android/server/wm/AppTaskImpl.java2
8 files changed, 115 insertions, 49 deletions
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index 41fdd0bfe477..7bf5c38b7fd4 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -49,6 +49,12 @@ public abstract class DreamManagerInternal {
* Called by the ActivityTaskManagerService to verify that the startDreamActivity
* 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
* active dream component.
*/
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 7734ffb0e0b0..0db97718b693 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -1054,6 +1054,7 @@ public class DreamService extends Service implements Window.Callback {
// DreamServiceWrapper.onActivityCreated.
if (!mWindowless) {
Intent i = new Intent(this, DreamActivity.class);
+ i.setPackage(getApplicationContext().getPackageName());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index eb0257e95b6c..bcf262d97235 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -51,6 +51,7 @@ import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -75,6 +76,7 @@ public final class DreamManagerService extends SystemService {
private final PowerManager mPowerManager;
private final PowerManagerInternal mPowerManagerInternal;
private final PowerManager.WakeLock mDozeWakeLock;
+ private final ActivityTaskManagerInternal mAtmInternal;
private Binder mCurrentDreamToken;
private ComponentName mCurrentDreamName;
@@ -97,6 +99,7 @@ public final class DreamManagerService extends SystemService {
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
+ mAtmInternal = getLocalService(ActivityTaskManagerInternal.class);
mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
mDozeConfig = new AmbientDisplayConfiguration(mContext);
}
@@ -383,8 +386,10 @@ public final class DreamManagerService extends SystemService {
PowerManager.WakeLock wakeLock = mPowerManager
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
- mHandler.post(wakeLock.wrap(
- () -> mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock)));
+ mHandler.post(wakeLock.wrap(() -> {
+ mAtmInternal.notifyDreamStateChanged(true);
+ mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock);
+ }));
}
private void stopDreamLocked(final boolean immediate) {
@@ -422,6 +427,7 @@ public final class DreamManagerService extends SystemService {
}
mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ mAtmInternal.notifyDreamStateChanged(false);
}
private void checkPermission(String permission) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ecafa69b1999..c1c844078d6f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -36,6 +36,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
import static android.app.WaitResult.INVALID_DELAY;
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_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -269,6 +270,8 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.service.dreams.DreamActivity;
+import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
import android.util.EventLog;
@@ -2035,6 +2038,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
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,
ActivityOptions options, ActivityRecord sourceRecord) {
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
&& canLaunchAssistActivity(launchedFromPackage)) {
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);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0ba186644cc3..7a6da6739dc1 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -341,7 +341,6 @@ class ActivityStarter {
int filterCallingUid;
PendingIntentRecord originatingPendingIntent;
boolean allowBackgroundActivityStart;
- boolean isDream;
/**
* If set to {@code true}, allows this activity start to look into
@@ -393,7 +392,6 @@ class ActivityStarter {
filterCallingUid = UserHandle.USER_NULL;
originatingPendingIntent = null;
allowBackgroundActivityStart = false;
- isDream = false;
}
/**
@@ -434,7 +432,6 @@ class ActivityStarter {
filterCallingUid = request.filterCallingUid;
originatingPendingIntent = request.originatingPendingIntent;
allowBackgroundActivityStart = request.allowBackgroundActivityStart;
- isDream = request.isDream;
}
/**
@@ -985,7 +982,7 @@ class ActivityStarter {
restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
request.originatingPendingIntent, request.allowBackgroundActivityStart,
- request.isDream, intent);
+ intent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
@@ -1195,7 +1192,7 @@ class ActivityStarter {
boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
final String callingPackage, int realCallingUid, int realCallingPid,
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
- boolean allowBackgroundActivityStart, boolean isDream, Intent intent) {
+ boolean allowBackgroundActivityStart, Intent intent) {
// don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(callingUid);
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
@@ -1203,10 +1200,6 @@ class ActivityStarter {
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
final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow =
@@ -2717,11 +2710,6 @@ class ActivityStarter {
return this;
}
- ActivityStarter setIsDream(boolean isDream) {
- mRequest.isDream = isDream;
- return this;
- }
-
void dump(PrintWriter pw, String prefix) {
prefix = prefix + " ";
pw.print(prefix);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 2263795f9442..d48df9ff8e6c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -290,6 +290,11 @@ public abstract class ActivityTaskManagerInternal {
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
* whenever it wants.
*
@@ -318,6 +323,7 @@ public abstract class ActivityTaskManagerInternal {
public abstract void clearHeavyWeightProcessIfEquals(WindowProcessController proc);
public abstract void finishHeavyWeightApp();
+ public abstract boolean isDreaming();
public abstract boolean isSleeping();
public abstract boolean isShuttingDown();
public abstract boolean shuttingDown(boolean booted, int timeout);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 4fff86099a4c..970212a63a55 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -212,7 +212,6 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.service.dreams.DreamActivity;
-import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.sysprop.DisplayProperties;
@@ -599,6 +598,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
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.
* This changes between TOP and TOP_SLEEPING to following mSleeping.
*/
@@ -1238,36 +1244,29 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- @Override
- public boolean startDreamActivity(Intent intent) {
- final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
+ private void enforceCallerIsDream(String callerPackageName) {
final long origId = Binder.clearCallingIdentity();
-
- // The dream activity is only called for non-doze dreams.
- final ComponentName currentDream = LocalServices.getService(DreamManagerInternal.class)
- .getActiveDreamComponent(/* doze= */ false);
-
- if (currentDream == null || currentDream.getPackageName() == null
- || !currentDream.getPackageName().equals(process.mInfo.packageName)) {
- Slog.e(TAG, "Calling package is not the current dream package. "
- + "Aborting startDreamActivity...");
- return false;
+ try {
+ if (!ActivityRecord.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());
final ActivityInfo a = new ActivityInfo();
a.theme = com.android.internal.R.style.Theme_Dream;
a.exported = true;
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.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE;
-
a.persistableMode = ActivityInfo.PERSIST_NEVER;
a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
@@ -1276,15 +1275,34 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
- try {
- getActivityStartController().obtainStarter(intent, "dream")
- .setActivityInfo(a)
- .setActivityOptions(options.toBundle())
- .setIsDream(true)
- .execute();
- return true;
- } finally {
- Binder.restoreCallingIdentity(origId);
+ synchronized (mGlobalLock) {
+ final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
+
+ 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";
+
+ 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(
null /* intent */, "moveTaskToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
- -1, callerApp, null, false, false, null)) {
+ -1, callerApp, null, false, null)) {
if (!isBackgroundActivityStartsEnabled()) {
return;
}
@@ -6337,6 +6355,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public void notifyDreamStateChanged(boolean dreaming) {
+ synchronized (mGlobalLock) {
+ mDreaming = dreaming;
+ }
+ }
+
+ @Override
public void setAllowAppSwitches(@NonNull String type, int uid, int userId) {
if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_OR_STOPPED)) {
return;
@@ -6438,6 +6463,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
+ @Override
+ public boolean isDreaming() {
+ synchronized (mGlobalLock) {
+ return mDreaming;
+ }
+ }
+
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public boolean isSleeping() {
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 4cce212cb779..8fa811915fc2 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -111,7 +111,7 @@ class AppTaskImpl extends IAppTask.Stub {
final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
null /* intent */, "moveToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
- callingPackage, -1, -1, callerApp, null, false, false, null)) {
+ callingPackage, -1, -1, callerApp, null, false, null)) {
if (!mService.isBackgroundActivityStartsEnabled()) {
return;
}