summaryrefslogtreecommitdiffstats
path: root/services/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java60
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java25
-rw-r--r--services/java/com/android/server/am/ActivityStack.java71
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java4
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java15
5 files changed, 143 insertions, 32 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c957ebb..e41f642 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1000,7 +1000,6 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int USER_SWITCH_TIMEOUT_MSG = 36;
static final int IMMERSIVE_MODE_LOCK_MSG = 37;
static final int PERSIST_URI_GRANTS = 38;
- static final int SET_FOCUSED_STACK = 39;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1493,18 +1492,6 @@ public final class ActivityManagerService extends ActivityManagerNative
writeGrantedUriPermissions();
break;
}
- case SET_FOCUSED_STACK: {
- synchronized (ActivityManagerService.this) {
- ActivityStack stack = mStackSupervisor.getStack(msg.arg1);
- if (stack != null) {
- ActivityRecord r = stack.topRunningActivityLocked(null);
- if (r != null) {
- setFocusedActivityLocked(r);
- }
- }
- }
- break;
- }
}
}
};
@@ -2081,7 +2068,26 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void setFocusedStack(int stackId) {
if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: stackId=" + stackId);
- mHandler.obtainMessage(SET_FOCUSED_STACK, stackId, 0).sendToTarget();
+ synchronized (ActivityManagerService.this) {
+ ActivityStack stack = mStackSupervisor.getStack(stackId);
+ if (stack != null) {
+ ActivityRecord r = stack.topRunningActivityLocked(null);
+ if (r != null) {
+ setFocusedActivityLocked(r);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void notifyActivityDrawn(IBinder token) {
+ if (DEBUG_VISBILITY) Slog.d(TAG, "notifyActivityDrawn: token=" + token);
+ synchronized (this) {
+ ActivityRecord r= mStackSupervisor.isInAnyStackLocked(token);
+ if (r != null) {
+ r.task.stack.notifyActivityDrawnLocked(r);
+ }
+ }
}
final void applyUpdateLockStateLocked(ActivityRecord r) {
@@ -8048,7 +8054,26 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void convertToOpaque(IBinder token) {
+ public void convertFromTranslucent(IBinder token) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ if (r.changeWindowTranslucency(true)) {
+ mWindowManager.setAppFullscreen(token, true);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
+ public void convertToTranslucent(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -8056,8 +8081,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (r == null) {
return;
}
- if (r.convertToOpaque()) {
- mWindowManager.setAppFullscreen(token);
+ if (r.changeWindowTranslucency(false)) {
+ r.task.stack.convertToTranslucent(r);
+ mWindowManager.setAppFullscreen(token, false);
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 4f09407..2ae9ed6 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.os.Trace;
+import com.android.internal.R.styleable;
import com.android.internal.app.ResolverActivity;
import com.android.server.AttributeCache;
import com.android.server.am.ActivityStack.ActivityState;
@@ -505,19 +506,23 @@ final class ActivityRecord {
}
}
- boolean convertToOpaque() {
- if (fullscreen) {
+ boolean changeWindowTranslucency(boolean toOpaque) {
+ if (fullscreen == toOpaque) {
return false;
}
-
- AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
- realTheme, com.android.internal.R.styleable.Window);
- if (ent != null && !ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false)) {
- fullscreen = true;
- ++task.numFullscreen;
+ AttributeCache.Entry ent =
+ AttributeCache.instance().get(packageName, realTheme, styleable.Window);
+ if (ent == null
+ || !ent.array.getBoolean(styleable.Window_windowIsTranslucent, false)
+ || ent.array.getBoolean(styleable.Window_windowIsFloating, false)) {
+ return false;
}
- return fullscreen;
+
+ // Keep track of the number of fullscreen activities in this task.
+ task.numFullscreen += toOpaque ? +1 : -1;
+
+ fullscreen = toOpaque;
+ return true;
}
void putInHistory() {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 98b3ce9..be03ee3 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -118,6 +118,10 @@ final class ActivityStack {
// is being started.
static final boolean SHOW_APP_STARTING_PREVIEW = true;
+ // How long to wait for all background Activities to redraw following a call to
+ // convertToTranslucent().
+ static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
+
enum ActivityState {
INITIALIZING,
RESUMED,
@@ -184,6 +188,16 @@ final class ActivityStack {
*/
ActivityRecord mLastStartedActivity = null;
+ // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
+ // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
+ // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
+ // Activity in mTranslucentActivityWaiting is notified via
+ // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
+ // background activity being drawn then the same call will be made with a true value.
+ ActivityRecord mTranslucentActivityWaiting = null;
+ ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent =
+ new ArrayList<ActivityRecord>();
+
/**
* Set when we know we are going to be calling updateConfiguration()
* soon, so want to skip intermediate config checks.
@@ -215,6 +229,7 @@ final class ActivityStack {
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
+ static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
static class ScheduleDestroyArgs {
final ProcessRecord mOwner;
@@ -285,7 +300,12 @@ final class ActivityStack {
synchronized (mService) {
destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
}
- }
+ } break;
+ case TRANSLUCENT_TIMEOUT_MSG: {
+ synchronized (mService) {
+ notifyActivityDrawnLocked(null);
+ }
+ } break;
}
}
}
@@ -952,6 +972,16 @@ final class ActivityStack {
TAG, "ensureActivitiesVisible behind " + top
+ " configChanges=0x" + Integer.toHexString(configChanges));
+ if (mTranslucentActivityWaiting != top) {
+ mUndrawnActivitiesBelowTopTranslucent.clear();
+ if (mTranslucentActivityWaiting != null) {
+ // Call the callback with a timeout indication.
+ notifyActivityDrawnLocked(null);
+ mTranslucentActivityWaiting = null;
+ }
+ mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
+ }
+
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = true;
@@ -1018,6 +1048,9 @@ final class ActivityStack {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Making visible and scheduling visibility: " + r);
try {
+ if (mTranslucentActivityWaiting != null) {
+ mUndrawnActivitiesBelowTopTranslucent.add(r);
+ }
mWindowManager.setAppVisibility(r.appToken, true);
r.sleeping = false;
r.app.pendingUiClean = true;
@@ -1091,6 +1124,42 @@ final class ActivityStack {
return showHomeBehindStack;
}
+ void convertToTranslucent(ActivityRecord r) {
+ mTranslucentActivityWaiting = r;
+ mUndrawnActivitiesBelowTopTranslucent.clear();
+ mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
+ }
+
+ /**
+ * Called as activities below the top translucent activity are redrawn. When the last one is
+ * redrawn notify the top activity by calling
+ * {@link Activity#onTranslucentConversionComplete}.
+ *
+ * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
+ * occurred and the activity will be notified immediately.
+ */
+ void notifyActivityDrawnLocked(ActivityRecord r) {
+ if ((r == null)
+ || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
+ mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
+ // The last undrawn activity below the top has just been drawn. If there is an
+ // opaque activity at the top, notify it that it can become translucent safely now.
+ final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
+ mTranslucentActivityWaiting = null;
+ mUndrawnActivitiesBelowTopTranslucent.clear();
+ mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
+
+ if (waitingActivity != null && waitingActivity.app != null &&
+ waitingActivity.app.thread != null) {
+ try {
+ waitingActivity.app.thread.scheduleTranslucentConversionComplete(
+ waitingActivity.appToken, r != null);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+
/**
* Ensure that the top activity in the stack is resumed.
*
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 63f91ac..d39798d 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2475,8 +2475,7 @@ public final class ActivityStackSupervisor {
public void handleMessage(Message msg) {
switch (msg.what) {
case IDLE_TIMEOUT_MSG: {
- if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
- Debug.getCallers(4));
+ if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
if (mService.mDidDexOpt) {
mService.mDidDexOpt = false;
Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
@@ -2489,6 +2488,7 @@ public final class ActivityStackSupervisor {
activityIdleInternal((ActivityRecord)msg.obj);
} break;
case IDLE_NOW_MSG: {
+ if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
activityIdleInternal((ActivityRecord)msg.obj);
} break;
case RESUME_TOP_ACTIVITY_MSG: {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index ee2ef37..50d267f 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -25,6 +25,7 @@ import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
import android.util.TimeUtils;
import android.view.IWindowId;
+
import com.android.internal.app.IBatteryStats;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
@@ -4117,10 +4118,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- public void setAppFullscreen(IBinder token) {
+ public void setAppFullscreen(IBinder token, boolean toOpaque) {
AppWindowToken atoken = findAppWindowToken(token);
if (atoken != null) {
- atoken.appFullscreen = true;
+ atoken.appFullscreen = toOpaque;
+ requestTraversal();
}
}
@@ -7020,6 +7022,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int CLIENT_FREEZE_TIMEOUT = 30;
public static final int TAP_OUTSIDE_STACK = 31;
+ public static final int NOTIFY_ACTIVITY_DRAWN = 32;
@Override
public void handleMessage(Message msg) {
@@ -7452,6 +7455,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+ break;
+ case NOTIFY_ACTIVITY_DRAWN:
+ try {
+ mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
+ } catch (RemoteException e) {
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -8759,6 +8769,7 @@ public class WindowManagerService extends IWindowManager.Stub
+ " interesting=" + numInteresting
+ " drawn=" + wtoken.numDrawnWindows);
wtoken.allDrawn = true;
+ mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
}
}
}