diff options
| author | Craig Mautner <cmautner@google.com> | 2013-04-18 10:01:00 -0700 |
|---|---|---|
| committer | Craig Mautner <cmautner@google.com> | 2013-04-18 10:02:38 -0700 |
| commit | a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72e (patch) | |
| tree | 04e386df3dfbb000010785a223916eeea0115584 | |
| parent | 29219d963d1ec29ddea3e5814eb82c2aeaccc1ac (diff) | |
| download | frameworks_base-a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72e.zip frameworks_base-a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72e.tar.gz frameworks_base-a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72e.tar.bz2 | |
Add transparent frame around focused stack.
- Also fix bugs when removing stack.
Change-Id: I3e0e3029f512f086601add00ccf34b2fea84296d
6 files changed, 182 insertions, 8 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4f0000e..f3be0ea 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -218,6 +218,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false; static final boolean DEBUG_MU = localLOGV || false; static final boolean DEBUG_IMMERSIVE = localLOGV || false; + static final boolean DEBUG_STACK = localLOGV || false; static final boolean VALIDATE_TOKENS = true; static final boolean SHOW_ACTIVITY_START_TIME = true; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 5aa056c..0711f74 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -82,6 +82,7 @@ final class ActivityStack { static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION; static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS; static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP; + static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK; static final boolean DEBUG_STATES = ActivityStackSupervisor.DEBUG_STATES; static final boolean DEBUG_ADD_REMOVE = ActivityStackSupervisor.DEBUG_ADD_REMOVE; @@ -2836,6 +2837,8 @@ final class ActivityStack { } final TaskRecord task = r.task; if (task != null && task.removeActivity(r)) { + if (DEBUG_STACK) Slog.i(TAG, + "removeActivityFromHistoryLocked: last activity removed from " + this); mStackSupervisor.removeTask(task); } r.takeFromHistory(); diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 8b946e4..7a6687e 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -72,6 +72,8 @@ import java.util.ArrayList; import java.util.List; public class ActivityStackSupervisor { + static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK; + static final boolean DEBUG = ActivityManagerService.DEBUG || false; static final boolean DEBUG_ADD_REMOVE = DEBUG || false; static final boolean DEBUG_APP = DEBUG || false; @@ -237,9 +239,11 @@ public class ActivityStackSupervisor { void removeTask(TaskRecord task) { final ActivityStack stack = task.stack; if (stack.removeTask(task) && !stack.isHomeStack()) { + if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack); mStacks.remove(stack); final int stackId = stack.mStackId; final int nextStackId = mService.mWindowManager.removeStack(stackId); + // TODO: Perhaps we need to let the ActivityManager determine the next focus... if (mFocusedStack.mStackId == stackId) { mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId); } diff --git a/services/java/com/android/server/wm/FocusedStackFrame.java b/services/java/com/android/server/wm/FocusedStackFrame.java new file mode 100644 index 0000000..29949ad --- /dev/null +++ b/services/java/com/android/server/wm/FocusedStackFrame.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static com.android.server.wm.WindowManagerService.DEBUG_STACK; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.Region; +import android.util.Slog; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceControl; +import android.view.SurfaceSession; + +class FocusedStackFrame { + private static final String TAG = "FocusedStackFrame"; + private static final int THICKNESS = 10; + private static final float ALPHA = 0.3f; + + private final SurfaceControl mSurfaceControl; + private final Surface mSurface = new Surface(); + private Rect mLastBounds = new Rect(); + private Rect mBounds = new Rect(); + private Rect mTmpDrawRect = new Rect(); + + public FocusedStackFrame(Display display, SurfaceSession session) { + SurfaceControl ctrl = null; + try { + ctrl = new SurfaceControl(session, "FocusedStackFrame", + 1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + ctrl.setLayerStack(display.getLayerStack()); + ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 102); + ctrl.setAlpha(ALPHA); + mSurface.copyFrom(ctrl); + } catch (SurfaceControl.OutOfResourcesException e) { + } + mSurfaceControl = ctrl; + } + + private void draw(Rect bounds, int color) { + if (DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() + + " color=" + Integer.toHexString(color)); + mTmpDrawRect.set(bounds); + Canvas c = null; + try { + c = mSurface.lockCanvas(mTmpDrawRect); + } catch (IllegalArgumentException e) { + } catch (Surface.OutOfResourcesException e) { + } + if (c == null) { + return; + } + + final int w = bounds.width(); + final int h = bounds.height(); + + // Top + mTmpDrawRect.set(0, 0, w, THICKNESS); + c.clipRect(mTmpDrawRect, Region.Op.REPLACE); + c.drawColor(color); + // Left (not including Top or Bottom stripe). + mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS); + c.clipRect(mTmpDrawRect, Region.Op.REPLACE); + c.drawColor(color); + // Right (not including Top or Bottom stripe). + mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS); + c.clipRect(mTmpDrawRect, Region.Op.REPLACE); + c.drawColor(color); + // Bottom + mTmpDrawRect.set(0, h - THICKNESS, w, h); + c.clipRect(mTmpDrawRect, Region.Op.REPLACE); + c.drawColor(color); + + mSurface.unlockCanvasAndPost(c); + } + + private void positionSurface(Rect bounds) { + if (DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString()); + mSurfaceControl.setSize(bounds.width(), bounds.height()); + mSurfaceControl.setPosition(bounds.left, bounds.top); + } + + // Note: caller responsible for being inside + // Surface.openTransaction() / closeTransaction() + public void setVisibility(boolean on) { + if (DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on + + " mLastBounds=" + mLastBounds.toShortString() + + " mBounds=" + mBounds.toShortString()); + if (mSurfaceControl == null) { + return; + } + if (on) { + if (!mLastBounds.equals(mBounds)) { + // Erase the previous rectangle. + positionSurface(mLastBounds); + draw(mLastBounds, Color.TRANSPARENT); + // Draw the latest rectangle. + positionSurface(mBounds); + draw(mBounds, Color.WHITE); + // Update the history. + mLastBounds.set(mBounds); + } + mSurfaceControl.show(); + } else { + mSurfaceControl.hide(); + } + } + + public void setBounds(Rect bounds) { + if (DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds); + mBounds.set(bounds); + } +} diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java index b195f0b..83f32e9 100644 --- a/services/java/com/android/server/wm/StackBox.java +++ b/services/java/com/android/server/wm/StackBox.java @@ -17,8 +17,11 @@ package com.android.server.wm; import android.graphics.Rect; +import android.util.Slog; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import static com.android.server.wm.WindowManagerService.DEBUG_STACK; +import static com.android.server.wm.WindowManagerService.TAG; import java.io.PrintWriter; import java.util.ArrayList; @@ -230,24 +233,28 @@ public class StackBox { * @return The first stackId of the resulting StackBox. */ int remove() { if (mStack != null) { + if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing stackId=" + mStack.mStackId); mDisplayContent.mStackHistory.remove(mStack); } mDisplayContent.layoutNeeded = true; if (mParent == null) { // This is the top-plane stack. + if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing top plane."); mDisplayContent.removeStackBox(this); return HOME_STACK_ID; } StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst; StackBox grandparent = mParent.mParent; + sibling.mParent = grandparent; if (grandparent == null) { // mParent is a top-plane stack. Now sibling will be. + if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent null"); mDisplayContent.removeStackBox(mParent); mDisplayContent.addStackBox(sibling, true); } else { - sibling.mParent = grandparent; + if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent getting sibling"); if (mParent.isFirstChild()) { grandparent.mFirst = sibling; } else { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index a16a8e6..d9a9d0b 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -401,6 +401,7 @@ public class WindowManagerService extends IWindowManager.Stub final SurfaceSession mFxSession; Watermark mWatermark; StrictModeFlash mStrictModeFlash; + FocusedStackFrame mFocusedStackFrame; final float[] mTmpFloats = new float[9]; @@ -793,6 +794,8 @@ public class WindowManagerService extends IWindowManager.Stub SurfaceControl.openTransaction(); try { createWatermarkInTransaction(); + mFocusedStackFrame = new FocusedStackFrame( + getDefaultDisplayContentLocked().getDisplay(), mFxSession); } finally { SurfaceControl.closeTransaction(); } @@ -3682,6 +3685,25 @@ public class WindowManagerService extends IWindowManager.Stub } } + void setFocusedStackFrame(TaskStack stack) { + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); + SurfaceControl.openTransaction(); + try { + if (stack == null) { + mFocusedStackFrame.setVisibility(false); + } else { + final StackBox box = stack.mStackBox; + final Rect bounds = box.mBounds; + final boolean multipleStacks = box.mParent != null; + mFocusedStackFrame.setBounds(bounds); + mFocusedStackFrame.setVisibility(multipleStacks); + } + } finally { + SurfaceControl.closeTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); + } + } + @Override public void setFocusedApp(IBinder token, boolean moveFocusNow) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -4746,13 +4768,16 @@ public class WindowManagerService extends IWindowManager.Stub } public int removeStack(int stackId) { - final TaskStack stack = mStackIdToStack.get(stackId); - if (stack != null) { - mStackIdToStack.delete(stackId); - int nextStackId = stack.remove(); - stack.getDisplayContent().layoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - return nextStackId; + synchronized (mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack != null) { + mStackIdToStack.delete(stackId); + int nextStackId = stack.remove(); + stack.getDisplayContent().layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + return nextStackId; + } + if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId); } return HOME_STACK_ID; } @@ -9235,6 +9260,10 @@ public class WindowManagerService extends IWindowManager.Stub } } + final TaskStack stack = mFocusedApp != null ? + mTaskIdToTask.get(mFocusedApp.groupId).mStack : null; + setFocusedStackFrame(stack); + // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. enableScreenIfNeededLocked(); |
