diff options
Diffstat (limited to 'services/core/java/com/android/server/wm')
20 files changed, 1325 insertions, 1029 deletions
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 37ca0db..91ce739 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -339,6 +339,7 @@ final class AccessibilityController { case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL: case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA: case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL: + case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL: case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: case WindowManager.LayoutParams.TYPE_SEARCH_BAR: case WindowManager.LayoutParams.TYPE_PHONE: @@ -620,9 +621,8 @@ final class AccessibilityController { final int windowCount = windowList.size(); for (int i = 0; i < windowCount; i++) { WindowState windowState = windowList.get(i); - if ((windowState.isOnScreen() || windowState.mAttrs.type == WindowManager - .LayoutParams.TYPE_UNIVERSE_BACKGROUND) - && !windowState.mWinAnimator.mEnterAnimationPending) { + if (windowState.isOnScreen() && + !windowState.mWinAnimator.mEnterAnimationPending) { outWindows.put(windowState.mLayer, windowState); } } @@ -670,7 +670,7 @@ final class AccessibilityController { TypedValue typedValue = new TypedValue(); context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight, typedValue, true); - final int borderColor = context.getResources().getColor(typedValue.resourceId); + final int borderColor = context.getColor(typedValue.resourceId); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mBorderWidth); @@ -1251,7 +1251,6 @@ final class AccessibilityController { && windowType != WindowManager.LayoutParams.TYPE_DRAG && windowType != WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER && windowType != WindowManager.LayoutParams.TYPE_POINTER - && windowType != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND && windowType != WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index c0d54e1..9033c9c 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -22,6 +22,7 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Debug; import android.os.Handler; +import android.os.IBinder; import android.os.IRemoteCallback; import android.util.Slog; import android.view.WindowManager; @@ -30,15 +31,22 @@ import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.ClipRectAnimation; +import android.view.animation.ClipRectLRAnimation; +import android.view.animation.ClipRectTBAnimation; import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; +import android.view.animation.TranslateXAnimation; +import android.view.animation.TranslateYAnimation; import com.android.internal.util.DumpUtils.Dump; import com.android.server.AttributeCache; import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; +import java.util.ArrayList; +import static android.view.WindowManagerInternal.AppTransitionListener; import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation; import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation; @@ -134,6 +142,7 @@ public class AppTransition implements Dump { private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5; private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6; private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7; + private static final int NEXT_TRANSIT_TYPE_CLIP_REVEAL = 8; private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; // These are the possible states for the enter/exit activities during a thumbnail transition @@ -169,19 +178,26 @@ public class AppTransition implements Dump { private final Interpolator mDecelerateInterpolator; private final Interpolator mThumbnailFadeInInterpolator; private final Interpolator mThumbnailFadeOutInterpolator; - private final Interpolator mThumbnailFastOutSlowInInterpolator; + private final Interpolator mLinearOutSlowInInterpolator; + private final Interpolator mFastOutSlowInInterpolator; + private final LinearInterpolator mLinearInterpolator; private int mCurrentUserId = 0; + private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>(); + AppTransition(Context context, Handler h) { mContext = context; mH = h; + mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.linear_out_slow_in); + mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, + com.android.internal.R.interpolator.fast_out_slow_in); + mLinearInterpolator = new LinearInterpolator(); mConfigShortAnimTime = context.getResources().getInteger( com.android.internal.R.integer.config_shortAnimTime); mDecelerateInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.decelerate_cubic); - mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, - com.android.internal.R.interpolator.fast_out_slow_in); mThumbnailFadeInInterpolator = new Interpolator() { @Override public float getInterpolation(float input) { @@ -276,12 +292,18 @@ public class AppTransition implements Dump { void prepare() { if (!isRunning()) { mAppTransitionState = APP_STATE_IDLE; + notifyAppTransitionPendingLocked(); } } - void goodToGo() { + void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) { mNextAppTransition = TRANSIT_UNSET; mAppTransitionState = APP_STATE_RUNNING; + notifyAppTransitionStartingLocked( + openingAppAnimator != null ? openingAppAnimator.mAppToken.token : null, + closingAppAnimator != null ? closingAppAnimator.mAppToken.token : null, + openingAppAnimator != null ? openingAppAnimator.animation : null, + closingAppAnimator != null ? closingAppAnimator.animation : null); } void clear() { @@ -294,6 +316,38 @@ public class AppTransition implements Dump { setAppTransition(AppTransition.TRANSIT_UNSET); clear(); setReady(); + notifyAppTransitionCancelledLocked(); + } + + void registerListenerLocked(AppTransitionListener listener) { + mListeners.add(listener); + } + + public void notifyAppTransitionFinishedLocked(AppWindowAnimator animator) { + IBinder token = animator != null ? animator.mAppToken.token : null; + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onAppTransitionFinishedLocked(token); + } + } + + private void notifyAppTransitionPendingLocked() { + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onAppTransitionPendingLocked(); + } + } + + private void notifyAppTransitionCancelledLocked() { + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onAppTransitionCancelledLocked(); + } + } + + private void notifyAppTransitionStartingLocked(IBinder openToken, + IBinder closeToken, Animation openAnimation, Animation closeAnimation) { + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onAppTransitionStartingLocked(openToken, closeToken, openAnimation, + closeAnimation); + } } private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) { @@ -447,6 +501,86 @@ public class AppTransition implements Dump { return a; } + private Animation createClipRevealAnimationLocked(int transit, boolean enter, Rect appFrame) { + final Animation anim; + if (enter) { + // Reveal will expand and move faster in horizontal direction + + // Start from upper left of start and move to final position + final int appWidth = appFrame.width(); + final int appHeight = appFrame.height(); + + // Start from size of launch icon, expand to full width/height + Animation clipAnimLR = new ClipRectLRAnimation( + (appWidth - mNextAppTransitionStartWidth) / 2, + (appWidth + mNextAppTransitionStartWidth) / 2, 0, appWidth); + clipAnimLR.setInterpolator(mLinearOutSlowInInterpolator); + clipAnimLR.setDuration(DEFAULT_APP_TRANSITION_DURATION); + Animation clipAnimTB = new ClipRectTBAnimation( + (appHeight - mNextAppTransitionStartHeight) / 2, + (appHeight + mNextAppTransitionStartHeight) / 2, 0, appHeight); + clipAnimTB.setInterpolator(mFastOutSlowInInterpolator); + clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION); + + // Start from middle of launch icon area, move to 0, 0 + int startMiddleX = mNextAppTransitionStartX + + (mNextAppTransitionStartWidth - appWidth) / 2 - appFrame.left; + int startMiddleY = mNextAppTransitionStartY + + (mNextAppTransitionStartHeight - appHeight) / 2 - appFrame.top; + + TranslateXAnimation translateX = new TranslateXAnimation( + Animation.ABSOLUTE, startMiddleX, Animation.ABSOLUTE, 0); + translateX.setInterpolator(mLinearOutSlowInInterpolator); + translateX.setDuration(DEFAULT_APP_TRANSITION_DURATION); + TranslateYAnimation translateY = new TranslateYAnimation( + Animation.ABSOLUTE, startMiddleY, Animation.ABSOLUTE, 0); + translateY.setInterpolator(mFastOutSlowInInterpolator); + translateY.setDuration(DEFAULT_APP_TRANSITION_DURATION); + + // Quick fade-in from icon to app window + final int alphaDuration = 100; + AlphaAnimation alpha = new AlphaAnimation(0.1f, 1); + alpha.setDuration(alphaDuration); + alpha.setInterpolator(mLinearInterpolator); + + AnimationSet set = new AnimationSet(false); + set.addAnimation(clipAnimLR); + set.addAnimation(clipAnimTB); + set.addAnimation(translateX); + set.addAnimation(translateY); + set.addAnimation(alpha); + set.initialize(appWidth, appHeight, appWidth, appHeight); + anim = set; + } else { + final long duration; + switch (transit) { + case TRANSIT_ACTIVITY_OPEN: + case TRANSIT_ACTIVITY_CLOSE: + duration = mConfigShortAnimTime; + break; + default: + duration = DEFAULT_APP_TRANSITION_DURATION; + break; + } + if (transit == TRANSIT_WALLPAPER_INTRA_OPEN || + transit == TRANSIT_WALLPAPER_INTRA_CLOSE) { + // If we are on top of the wallpaper, we need an animation that + // correctly handles the wallpaper staying static behind all of + // the animated elements. To do this, will just have the existing + // element fade out. + anim = new AlphaAnimation(1, 0); + anim.setDetachWallpaper(true); + } else { + // For normal animations, the exiting element just holds in place. + anim = new AlphaAnimation(1, 1); + } + anim.setInterpolator(mDecelerateInterpolator); + anim.setDuration(duration); + anim.setFillAfter(true); + } + return anim; + } + /** * Prepares the specified animation with a standard duration, interpolator, etc. */ @@ -522,14 +656,14 @@ public class AppTransition implements Dump { Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW, mNextAppTransitionStartX + (thumbWidth / 2f), mNextAppTransitionStartY + (thumbHeight / 2f)); - scale.setInterpolator(mThumbnailFastOutSlowInInterpolator); + scale.setInterpolator(mFastOutSlowInInterpolator); scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); Animation alpha = new AlphaAnimation(1, 0); alpha.setInterpolator(mThumbnailFadeOutInterpolator); alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION); Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY + mNextAppTransitionInsets.top); - translate.setInterpolator(mThumbnailFastOutSlowInInterpolator); + translate.setInterpolator(mFastOutSlowInInterpolator); translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); // This AnimationSet uses the Interpolators assigned above. @@ -543,14 +677,14 @@ public class AppTransition implements Dump { Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f, mNextAppTransitionStartX + (thumbWidth / 2f), mNextAppTransitionStartY + (thumbHeight / 2f)); - scale.setInterpolator(mThumbnailFastOutSlowInInterpolator); + scale.setInterpolator(mFastOutSlowInInterpolator); scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); Animation alpha = new AlphaAnimation(0f, 1f); alpha.setInterpolator(mThumbnailFadeInInterpolator); alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION); Animation translate = new TranslateAnimation(0, 0, -unscaledStartY + mNextAppTransitionInsets.top, 0); - translate.setInterpolator(mThumbnailFastOutSlowInInterpolator); + translate.setInterpolator(mFastOutSlowInInterpolator); translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION); // This AnimationSet uses the Interpolators assigned above. @@ -562,7 +696,7 @@ public class AppTransition implements Dump { } return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0, - mThumbnailFastOutSlowInInterpolator); + mFastOutSlowInInterpolator); } /** @@ -698,7 +832,7 @@ public class AppTransition implements Dump { int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION, THUMBNAIL_APP_TRANSITION_DURATION); return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration, - mThumbnailFastOutSlowInInterpolator); + mFastOutSlowInInterpolator); } /** @@ -809,7 +943,7 @@ public class AppTransition implements Dump { Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int appWidth, int appHeight, int orientation, Rect containingFrame, Rect contentInsets, - boolean isFullScreen, boolean isVoiceInteraction) { + Rect appFrame, boolean isFullScreen, boolean isVoiceInteraction) { Animation a; if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN || transit == TRANSIT_TASK_OPEN @@ -845,6 +979,12 @@ public class AppTransition implements Dump { "applyAnimation:" + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE" + " transit=" + transit + " Callers=" + Debug.getCallers(3)); + } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) { + a = createClipRevealAnimationLocked(transit, enter, appFrame); + if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, + "applyAnimation:" + + " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL" + + " Callers=" + Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) { a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, @@ -987,6 +1127,19 @@ public class AppTransition implements Dump { } } + void overridePendingAppTransitionClipReveal(int startX, int startY, + int startWidth, int startHeight) { + if (isTransitionSet()) { + mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL; + mNextAppTransitionStartX = startX; + mNextAppTransitionStartY = startY; + mNextAppTransitionStartWidth = startWidth; + mNextAppTransitionStartHeight = startHeight; + postAnimationCallback(); + mNextAppTransitionCallback = null; + } + } + void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp) { if (isTransitionSet()) { @@ -1130,32 +1283,34 @@ public class AppTransition implements Dump { } @Override - public void dump(PrintWriter pw) { - pw.print(" " + this); - pw.print(" mAppTransitionState="); pw.println(appStateToString()); + public void dump(PrintWriter pw, String prefix) { + pw.print(prefix); pw.println(this); + pw.print(prefix); pw.print("mAppTransitionState="); pw.println(appStateToString()); if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) { - pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString()); + pw.print(prefix); pw.print("mNextAppTransitionType="); + pw.println(transitTypeToString()); } switch (mNextAppTransitionType) { case NEXT_TRANSIT_TYPE_CUSTOM: - pw.print(" mNextAppTransitionPackage="); + pw.print(prefix); pw.print("mNextAppTransitionPackage="); pw.println(mNextAppTransitionPackage); - pw.print(" mNextAppTransitionEnter=0x"); + pw.print(prefix); pw.print("mNextAppTransitionEnter=0x"); pw.print(Integer.toHexString(mNextAppTransitionEnter)); pw.print(" mNextAppTransitionExit=0x"); pw.println(Integer.toHexString(mNextAppTransitionExit)); break; case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE: - pw.print(" mNextAppTransitionPackage="); + pw.print(prefix); pw.print("mNextAppTransitionPackage="); pw.println(mNextAppTransitionPackage); - pw.print(" mNextAppTransitionInPlace=0x"); + pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x"); pw.print(Integer.toHexString(mNextAppTransitionInPlace)); break; case NEXT_TRANSIT_TYPE_SCALE_UP: - pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); + pw.print(prefix); pw.print("mNextAppTransitionStartX="); + pw.print(mNextAppTransitionStartX); pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY); - pw.print(" mNextAppTransitionStartWidth="); + pw.print(prefix); pw.print("mNextAppTransitionStartWidth="); pw.print(mNextAppTransitionStartWidth); pw.print(" mNextAppTransitionStartHeight="); pw.println(mNextAppTransitionStartHeight); @@ -1164,22 +1319,23 @@ public class AppTransition implements Dump { case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN: case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP: case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN: - pw.print(" mNextAppTransitionThumbnail="); + pw.print(prefix); pw.print("mNextAppTransitionThumbnail="); pw.print(mNextAppTransitionThumbnail); pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX); pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY); - pw.print(" mNextAppTransitionStartWidth="); + pw.print(prefix); pw.print("mNextAppTransitionStartWidth="); pw.print(mNextAppTransitionStartWidth); pw.print(" mNextAppTransitionStartHeight="); pw.println(mNextAppTransitionStartHeight); - pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp); + pw.print(prefix); pw.print("mNextAppTransitionScaleUp="); + pw.println(mNextAppTransitionScaleUp); break; } if (mNextAppTransitionCallback != null) { - pw.print(" mNextAppTransitionCallback="); - pw.println(mNextAppTransitionCallback); + pw.print(prefix); pw.print("mNextAppTransitionCallback="); + pw.println(mNextAppTransitionCallback); } } diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 5c81126..55ec9fc 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -17,7 +17,6 @@ package com.android.server.wm; import android.graphics.Matrix; -import android.os.RemoteException; import android.util.Slog; import android.util.TimeUtils; import android.view.Display; @@ -142,6 +141,10 @@ public class AppWindowAnimator { } } + public boolean isAnimating() { + return animation != null || mAppToken.inPendingTransaction; + } + public void clearThumbnail() { if (thumbnail != null) { thumbnail.destroy(); @@ -239,7 +242,7 @@ public class AppWindowAnimator { } // This must be called while inside a transaction. - boolean stepAnimationLocked(long currentTime) { + boolean stepAnimationLocked(long currentTime, final int displayId) { if (mService.okToDisplay()) { // We will run animations as long as the display isn't frozen. @@ -289,7 +292,7 @@ public class AppWindowAnimator { } mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, - "AppWindowToken"); + "AppWindowToken", displayId); clearAnimation(); animating = false; @@ -312,23 +315,7 @@ public class AppWindowAnimator { for (int i = 0; i < numAllAppWinAnimators; i++) { mAllAppWinAnimators.get(i).finishExit(); } - if (mAppToken.mLaunchTaskBehind) { - try { - mService.mActivityManager.notifyLaunchTaskBehindComplete(mAppToken.token); - } catch (RemoteException e) { - } - mAppToken.mLaunchTaskBehind = false; - } else { - mAppToken.updateReportedVisibilityLocked(); - if (mAppToken.mEnteringAnimation) { - mAppToken.mEnteringAnimation = false; - try { - mService.mActivityManager.notifyEnterAnimationComplete(mAppToken.token); - } catch (RemoteException e) { - } - } - } - + mService.mAppTransition.notifyAppTransitionFinishedLocked(this); return false; } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index da25c53..a210223 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -52,11 +52,11 @@ class AppWindowToken extends WindowToken { final boolean voiceInteraction; - int groupId = -1; + Task mTask; boolean appFullscreen; int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean layoutConfigChanges; - boolean showWhenLocked; + boolean showForAllUsers; // The input dispatching timeout for this application token in nanoseconds. long inputDispatchingTimeoutNanos; @@ -107,7 +107,7 @@ class AppWindowToken extends WindowToken { // Input application handle used by the input dispatcher. final InputApplicationHandle mInputApplicationHandle; - boolean mDeferRemoval; + boolean mIsExiting; boolean mLaunchTaskBehind; boolean mEnteringAnimation; @@ -252,6 +252,21 @@ class AppWindowToken extends WindowToken { return false; } + void removeAppFromTaskLocked() { + mIsExiting = false; + removeAllWindows(); + + // Use local variable because removeAppToken will null out mTask. + final Task task = mTask; + if (task != null) { + if (!task.removeAppToken(this)) { + Slog.e(WindowManagerService.TAG, "removeAppFromTaskLocked: token=" + this + + " not found."); + } + task.mStack.mExitingAppTokens.remove(this); + } + } + @Override void removeAllWindows() { for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; @@ -266,8 +281,10 @@ class AppWindowToken extends WindowToken { Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win); } - win.mService.removeWindowLocked(win.mSession, win); + service.removeWindowLocked(win); } + allAppWindows.clear(); + windows.clear(); } @Override @@ -279,8 +296,8 @@ class AppWindowToken extends WindowToken { if (allAppWindows.size() > 0) { pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows); } - pw.print(prefix); pw.print("groupId="); pw.print(groupId); - pw.print(" appFullscreen="); pw.print(appFullscreen); + pw.print(prefix); pw.print("task="); pw.println(mTask); + pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen); pw.print(" requestedOrientation="); pw.println(requestedOrientation); pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested); pw.print(" clientHidden="); pw.print(clientHidden); @@ -304,11 +321,11 @@ class AppWindowToken extends WindowToken { pw.print(prefix); pw.print("inPendingTransaction="); pw.println(inPendingTransaction); } - if (startingData != null || removed || firstWindowDrawn || mDeferRemoval) { + if (startingData != null || removed || firstWindowDrawn || mIsExiting) { pw.print(prefix); pw.print("startingData="); pw.print(startingData); pw.print(" removed="); pw.print(removed); pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); - pw.print(" mDeferRemoval="); pw.println(mDeferRemoval); + pw.print(" mIsExiting="); pw.println(mIsExiting); } if (startingWindow != null || startingView != null || startingDisplayed || startingMoved) { diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java index 3f5ae56..e385be3 100644 --- a/services/core/java/com/android/server/wm/DimLayer.java +++ b/services/core/java/com/android/server/wm/DimLayer.java @@ -168,24 +168,17 @@ public class DimLayer { mLastBounds.set(mBounds); } - /** - * @param bounds The new bounds to set - * @param inTransaction Whether the call is made within a surface transaction. - */ - void setBounds(Rect bounds, boolean inTransaction) { + /** @param bounds The new bounds to set */ + void setBounds(Rect bounds) { mBounds.set(bounds); if (isDimming() && !mLastBounds.equals(bounds)) { try { - if (!inTransaction) { - SurfaceControl.openTransaction(); - } + SurfaceControl.openTransaction(); adjustBounds(); } catch (RuntimeException e) { Slog.w(TAG, "Failure setting size", e); } finally { - if (!inTransaction) { - SurfaceControl.closeTransaction(); - } + SurfaceControl.closeTransaction(); } } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4f20f50..f914369 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -66,6 +66,7 @@ class DisplayContent { int mBaseDisplayWidth = 0; int mBaseDisplayHeight = 0; int mBaseDisplayDensity = 0; + boolean mDisplayScalingDisabled; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final Display mDisplay; @@ -241,23 +242,24 @@ class DisplayContent { mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); } } - mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); + if (mTapDetector != null) { + mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion); + } } - void switchUserStacks(int newUserId) { + void switchUserStacks() { final WindowList windows = getWindowList(); for (int i = 0; i < windows.size(); i++) { final WindowState win = windows.get(i); if (win.isHiddenFromUserLocked()) { - if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding " - + win + ", attrs=" + win.mAttrs.type + ", belonging to " - + win.mOwnerUid); + if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing, hiding " + win + + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); win.hideLw(false); } } for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - mStacks.get(stackNdx).switchUser(newUserId); + mStacks.get(stackNdx).switchUser(); } } @@ -328,16 +330,10 @@ class DisplayContent { AppTokenList tokens = task.mAppTokens; for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { AppWindowToken wtoken = tokens.get(tokenNdx); - if (wtoken.mDeferRemoval) { - stack.mExitingAppTokens.remove(wtoken); - wtoken.mDeferRemoval = false; - mService.removeAppFromTaskLocked(wtoken); + if (wtoken.mIsExiting) { + wtoken.removeAppFromTaskLocked(); } } - if (task.mDeferRemoval) { - task.mDeferRemoval = false; - mService.removeTaskLocked(task); - } } } } @@ -346,6 +342,12 @@ class DisplayContent { } } + static int deltaRotation(int oldRotation, int newRotation) { + int delta = newRotation - oldRotation; + if (delta < 0) delta += 4; + return delta; + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId); final String subPrefix = " " + prefix; @@ -359,6 +361,9 @@ class DisplayContent { pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight); pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi"); } + if (mDisplayScalingDisabled) { + pw.println(" noscale"); + } pw.print(" cur="); pw.print(mDisplayInfo.logicalWidth); pw.print("x"); pw.print(mDisplayInfo.logicalHeight); @@ -385,7 +390,7 @@ class DisplayContent { ArrayList<Task> tasks = stack.getTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { final Task task = tasks.get(taskNdx); - pw.print(" mTaskId="); pw.println(task.taskId); + pw.print(" mTaskId="); pw.println(task.mTaskId); AppTokenList tokens = task.mAppTokens; for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx, ++ndx) { final AppWindowToken wtoken = tokens.get(tokenNdx); diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index c6951bd..1a125d4 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -24,6 +24,7 @@ import com.android.server.wm.WindowManagerService.H; import android.content.ClipData; import android.content.ClipDescription; import android.graphics.Point; +import android.graphics.Rect; import android.graphics.Region; import android.os.IBinder; import android.os.Message; @@ -63,6 +64,7 @@ class DragState { Display mDisplay; private final Region mTmpRegion = new Region(); + private final Rect mTmpRect = new Rect(); DragState(WindowManagerService service, IBinder token, SurfaceControl surface, int flags, IBinder localWin) { @@ -411,6 +413,12 @@ class DragState { continue; } + child.getStackBounds(mTmpRect); + if (!mTmpRect.contains(x, y)) { + // outside of this window's activity stack == don't tell about drags + continue; + } + child.getTouchableRegion(mTmpRegion); final int touchFlags = flags & diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java index 5e4bd8b..4c8a6f9 100644 --- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java +++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java @@ -25,7 +25,6 @@ import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.util.Slog; import android.view.Display; import android.view.Surface; import android.view.Surface.OutOfResourcesException; diff --git a/services/core/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedStackFrame.java index f1f5fe8..826fe97 100644 --- a/services/core/java/com/android/server/wm/FocusedStackFrame.java +++ b/services/core/java/com/android/server/wm/FocusedStackFrame.java @@ -16,14 +16,14 @@ package com.android.server.wm; -import static com.android.server.wm.WindowManagerService.DEBUG_STACK; import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE; +import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; -import android.graphics.Region; import android.util.Slog; import android.view.Display; import android.view.Surface.OutOfResourcesException; @@ -35,14 +35,17 @@ import com.android.server.wm.WindowStateAnimator.SurfaceTrace; class FocusedStackFrame { private static final String TAG = "FocusedStackFrame"; - private static final int THICKNESS = 10; + private static final boolean DEBUG = false; + private static final int THICKNESS = 2; private static final float ALPHA = 0.3f; private final SurfaceControl mSurfaceControl; private final Surface mSurface = new Surface(); + private final Paint mInnerPaint = new Paint(); + private final Paint mOuterPaint = new Paint(); + private final Rect mBounds = new Rect(); private final Rect mLastBounds = new Rect(); - final Rect mBounds = new Rect(); - private final Rect mTmpDrawRect = new Rect(); + private int mLayer = -1; public FocusedStackFrame(Display display, SurfaceSession session) { SurfaceControl ctrl = null; @@ -60,83 +63,84 @@ class FocusedStackFrame { } catch (OutOfResourcesException e) { } mSurfaceControl = ctrl; + + mInnerPaint.setStyle(Paint.Style.STROKE); + mInnerPaint.setStrokeWidth(THICKNESS); + mInnerPaint.setColor(Color.WHITE); + mOuterPaint.setStyle(Paint.Style.STROKE); + mOuterPaint.setStrokeWidth(THICKNESS); + mOuterPaint.setColor(Color.BLACK); } - private void draw(Rect bounds, int color) { - if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() + - " color=" + Integer.toHexString(color)); - mTmpDrawRect.set(bounds); + private void draw() { + if (mLastBounds.isEmpty()) { + // Currently unset. Set it. + mLastBounds.set(mBounds); + } + + if (DEBUG) Slog.i(TAG, "draw: mBounds=" + mBounds + " mLastBounds=" + mLastBounds); + Canvas c = null; try { - c = mSurface.lockCanvas(mTmpDrawRect); + c = mSurface.lockCanvas(mLastBounds); } catch (IllegalArgumentException e) { + Slog.e(TAG, "Unable to lock canvas", e); } catch (Surface.OutOfResourcesException e) { + Slog.e(TAG, "Unable to lock canvas", e); } if (c == null) { + if (DEBUG) Slog.w(TAG, "Canvas is 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); - + c.drawRect(0, 0, mBounds.width(), mBounds.height(), mOuterPaint); + c.drawRect(THICKNESS, THICKNESS, mBounds.width() - THICKNESS, mBounds.height() - THICKNESS, + mInnerPaint); + if (DEBUG) Slog.w(TAG, "c.width=" + c.getWidth() + " c.height=" + c.getHeight() + + " c.clip=" + c .getClipBounds()); mSurface.unlockCanvasAndPost(c); + mLastBounds.set(mBounds); } - private void positionSurface(Rect bounds) { - if (false && 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 (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on + - " mLastBounds=" + mLastBounds.toShortString() + - " mBounds=" + mBounds.toShortString()); + private void setupSurface(boolean visible) { 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); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setupSurface"); + SurfaceControl.openTransaction(); + try { + if (visible) { + mSurfaceControl.setPosition(mBounds.left, mBounds.top); + mSurfaceControl.setSize(mBounds.width(), mBounds.height()); + mSurfaceControl.show(); + } else { + mSurfaceControl.hide(); } - mSurfaceControl.show(); - } else { - mSurfaceControl.hide(); + } finally { + SurfaceControl.closeTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setupSurface"); } } - public void setBounds(TaskStack stack) { - stack.getBounds(mBounds); - if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds); + void setVisibility(TaskStack stack) { + if (stack == null || stack.isFullscreen()) { + setupSurface(false); + } else { + stack.getBounds(mBounds); + setupSurface(true); + if (!mBounds.equals(mLastBounds)) { + draw(); + } + } } - public void setLayer(int layer) { - mSurfaceControl.setLayer(layer); + // Note: caller responsible for being inside + // Surface.openTransaction() / closeTransaction() + void setLayer(int layer) { + if (mLayer == layer) { + return; + } + mLayer = layer; + mSurfaceControl.setLayer(mLayer); } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index ad50e05a..c24fcb3 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -78,7 +78,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { WindowState windowState = (WindowState) inputWindowHandle.windowState; if (windowState != null) { Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState); - mService.removeWindowLocked(windowState.mSession, windowState); + mService.removeWindowLocked(windowState); } } } @@ -239,9 +239,6 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { // As an optimization, we could try to prune the list of windows but this turns // out to be difficult because only the native code knows for sure which window // currently has touch focus. - final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground; - final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer; - boolean addedUniverse = false; boolean disableWallpaperTouchEvents = false; // If there's a drag in flight, provide a pseudowindow to catch drag input @@ -299,20 +296,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { mService.mDragState.sendDragStartedIfNeededLw(child); } - if (universeBackground != null && !addedUniverse - && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) { - final WindowState u = universeBackground.mWin; - if (u.mInputChannel != null && u.mInputWindowHandle != null) { - addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags, - u.mAttrs.type, true, u == mInputFocus, false); - } - addedUniverse = true; - } - - if (child.mWinAnimator != universeBackground) { - addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible, - hasFocus, hasWallpaper); - } + addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible, hasFocus, + hasWallpaper); } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index f79896b..7dd716e 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -291,12 +291,6 @@ class ScreenRotationAnimation { return mSurfaceControl != null; } - static int deltaRotation(int oldRotation, int newRotation) { - int delta = newRotation - oldRotation; - if (delta < 0) delta += 4; - return delta; - } - private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) { if (mSurfaceControl != null) { matrix.getValues(mTmpFloats); @@ -352,7 +346,7 @@ class ScreenRotationAnimation { // Compute the transformation matrix that must be applied // to the snapshot to make it stay in the same original position // with the current screen rotation. - int delta = deltaRotation(rotation, Surface.ROTATION_0); + int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0); createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix); if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta); @@ -391,7 +385,7 @@ class ScreenRotationAnimation { boolean firstStart = false; // Figure out how the screen has moved from the original rotation. - int delta = deltaRotation(mCurRotation, mOriginalRotation); + int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation); if (TWO_PHASE_ANIMATION && mFinishExitAnimation == null && (!dismissing || delta != Surface.ROTATION_0)) { diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index a1d145c..487483e 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -446,20 +446,6 @@ final class Session extends IWindowSession.Stub mService.wallpaperCommandComplete(window, result); } - public void setUniverseTransform(IBinder window, float alpha, float offx, float offy, - float dsdx, float dtdx, float dsdy, float dtdy) { - synchronized(mService.mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - mService.setUniverseTransformLocked( - mService.windowForClientLocked(this, window, true), - alpha, offx, offy, dsdx, dtdx, dsdy, dtdy); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { synchronized(mService.mWindowMap) { final long identity = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index b49b87c..0c3cf65 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -17,22 +17,25 @@ package com.android.server.wm; import static com.android.server.wm.WindowManagerService.TAG; +import static com.android.server.wm.WindowManagerService.DEBUG_STACK; import android.util.EventLog; import android.util.Slog; +import com.android.server.EventLogTags; class Task { TaskStack mStack; final AppTokenList mAppTokens = new AppTokenList(); - final int taskId; + final int mTaskId; final int mUserId; boolean mDeferRemoval = false; + final WindowManagerService mService; - Task(AppWindowToken wtoken, TaskStack stack, int userId) { - taskId = wtoken.groupId; - mAppTokens.add(wtoken); + Task(int taskId, TaskStack stack, int userId, WindowManagerService service) { + mTaskId = taskId; mStack = stack; mUserId = userId; + mService = service; } DisplayContent getDisplayContent() { @@ -41,22 +44,60 @@ class Task { void addAppToken(int addPos, AppWindowToken wtoken) { final int lastPos = mAppTokens.size(); - for (int pos = 0; pos < lastPos && pos < addPos; ++pos) { - if (mAppTokens.get(pos).removed) { - // addPos assumes removed tokens are actually gone. - ++addPos; + if (addPos >= lastPos) { + addPos = lastPos; + } else { + for (int pos = 0; pos < lastPos && pos < addPos; ++pos) { + if (mAppTokens.get(pos).removed) { + // addPos assumes removed tokens are actually gone. + ++addPos; + } } } mAppTokens.add(addPos, wtoken); + wtoken.mTask = this; mDeferRemoval = false; } + void removeLocked() { + if (!mAppTokens.isEmpty() && mStack.isAnimating()) { + if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId); + mDeferRemoval = true; + return; + } + if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId); + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask"); + mDeferRemoval = false; + mStack.removeTask(this); + mService.mTaskIdToTask.delete(mTaskId); + } + + void moveTaskToStack(TaskStack stack, boolean toTop) { + if (stack == mStack) { + return; + } + if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId + + " from stack=" + mStack); + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask"); + if (mStack != null) { + mStack.removeTask(this); + } + stack.addTask(this, toTop); + } + boolean removeAppToken(AppWindowToken wtoken) { boolean removed = mAppTokens.remove(wtoken); if (mAppTokens.size() == 0) { - EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId, + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeAppToken: last token"); + if (mDeferRemoval) { + removeLocked(); + } } + wtoken.mTask = null; + /* Leave mTaskId for now, it might be useful for debug + wtoken.mTaskId = -1; + */ return removed; } @@ -66,8 +107,13 @@ class Task { } } + boolean showForAllUsers() { + final int tokensCount = mAppTokens.size(); + return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers; + } + @Override public String toString() { - return "{taskId=" + taskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}"; + return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}"; } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index d313e3f..7cdf8b2 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -19,11 +19,15 @@ package com.android.server.wm; import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerService.TAG; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Debug; +import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; import android.util.TypedValue; +import android.view.Surface; + import com.android.server.EventLogTags; import java.io.PrintWriter; @@ -49,6 +53,8 @@ public class TaskStack { /** For comparison with DisplayContent bounds. */ private Rect mTmpRect = new Rect(); + /** For handling display rotations. */ + private Rect mTmpRect2 = new Rect(); /** Content limits relative to the DisplayContent this sits in. */ private Rect mBounds = new Rect(); @@ -78,9 +84,24 @@ public class TaskStack { /** Detach this stack from its display when animation completes. */ boolean mDeferDetach; + // Contains configurations settings that are different from the global configuration due to + // stack specific operations. E.g. {@link #setBounds}. + Configuration mOverrideConfig; + // True if the stack was forced to fullscreen disregarding the override configuration. + private boolean mForceFullscreen; + // The {@link #mBounds} before the stack was forced to fullscreen. Will be restored as the + // stack bounds once the stack is no longer forced to fullscreen. + final private Rect mPreForceFullscreenBounds; + + // Device rotation as of the last time {@link #mBounds} was set. + int mRotation; + TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; + mOverrideConfig = Configuration.EMPTY; + mForceFullscreen = false; + mPreForceFullscreenBounds = new Rect(); // TODO: remove bounds from log, they are always 0. EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top, mBounds.right, mBounds.bottom); @@ -95,8 +116,6 @@ public class TaskStack { } void resizeWindows() { - final boolean underStatusBar = mBounds.top == 0; - final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; @@ -109,27 +128,40 @@ public class TaskStack { "setBounds: Resizing " + win); resizingWindows.add(win); } - win.mUnderStatusBar = underStatusBar; } } } } + /** Set the stack bounds. Passing in null sets the bounds to fullscreen. */ boolean setBounds(Rect bounds) { boolean oldFullscreen = mFullscreen; + int rotation = Surface.ROTATION_0; if (mDisplayContent != null) { mDisplayContent.getLogicalDisplayRect(mTmpRect); - mFullscreen = mTmpRect.equals(bounds); + rotation = mDisplayContent.getDisplayInfo().rotation; + if (bounds == null) { + bounds = mTmpRect; + mFullscreen = true; + } else { + bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect + mFullscreen = mTmpRect.equals(bounds); + } } - if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) { + if (bounds == null) { + // Can't set to fullscreen if we don't have a display to get bounds from... + return false; + } + if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) { return false; } - mDimLayer.setBounds(bounds, false); - mAnimationBackgroundSurface.setBounds(bounds, false); + mDimLayer.setBounds(bounds); + mAnimationBackgroundSurface.setBounds(bounds); mBounds.set(bounds); - + mRotation = rotation; + updateOverrideConfiguration(); return true; } @@ -137,10 +169,67 @@ public class TaskStack { out.set(mBounds); } + private void updateOverrideConfiguration() { + final Configuration serviceConfig = mService.mCurConfiguration; + if (mFullscreen) { + mOverrideConfig = Configuration.EMPTY; + return; + } + + if (mOverrideConfig == Configuration.EMPTY) { + mOverrideConfig = new Configuration(); + } + + // TODO(multidisplay): Update Dp to that of display stack is on. + final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; + mOverrideConfig.screenWidthDp = + Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); + mOverrideConfig.screenHeightDp = + Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); + mOverrideConfig.smallestScreenWidthDp = + Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); + mOverrideConfig.orientation = + (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) + ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; + } + void updateDisplayInfo() { - if (mFullscreen && mDisplayContent != null) { + if (mFullscreen) { + setBounds(null); + } else if (mDisplayContent != null) { + final int newRotation = mDisplayContent.getDisplayInfo().rotation; + if (mRotation == newRotation) { + return; + } + + // Device rotation changed. We don't want the stack to move around on the screen when + // this happens, so update the stack bounds so it stays in the same place. + final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation); mDisplayContent.getLogicalDisplayRect(mTmpRect); - setBounds(mTmpRect); + switch (rotationDelta) { + case Surface.ROTATION_0: + mTmpRect2.set(mBounds); + break; + case Surface.ROTATION_90: + mTmpRect2.top = mTmpRect.bottom - mBounds.right; + mTmpRect2.left = mBounds.top; + mTmpRect2.right = mTmpRect2.left + mBounds.height(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); + break; + case Surface.ROTATION_180: + mTmpRect2.top = mTmpRect.bottom - mBounds.bottom; + mTmpRect2.left = mTmpRect.right - mBounds.right; + mTmpRect2.right = mTmpRect2.left + mBounds.width(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.height(); + break; + case Surface.ROTATION_270: + mTmpRect2.top = mBounds.left; + mTmpRect2.left = mTmpRect.right - mBounds.bottom; + mTmpRect2.right = mTmpRect2.left + mBounds.height(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); + break; + } + setBounds(mTmpRect2); } } @@ -148,6 +237,28 @@ public class TaskStack { return mFullscreen; } + /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen. + * Returns true if something happened. + */ + boolean forceFullscreen(boolean forceFullscreen) { + if (mForceFullscreen == forceFullscreen) { + return false; + } + mForceFullscreen = forceFullscreen; + if (forceFullscreen) { + if (mFullscreen) { + return false; + } + mPreForceFullscreenBounds.set(mBounds); + return setBounds(null); + } else { + if (!mFullscreen || mPreForceFullscreenBounds.isEmpty()) { + return false; + } + return setBounds(mPreForceFullscreenBounds); + } + } + boolean isAnimating() { for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; @@ -164,21 +275,28 @@ public class TaskStack { return false; } + void addTask(Task task, boolean toTop) { + addTask(task, toTop, task.showForAllUsers()); + } + /** * Put a Task in this stack. Used for adding and moving. * @param task The task to add. * @param toTop Whether to add it to the top or bottom. + * @param showForAllUsers Whether to show the task regardless of the current user. */ - void addTask(Task task, boolean toTop) { + void addTask(Task task, boolean toTop, boolean showForAllUsers) { int stackNdx; if (!toTop) { stackNdx = 0; } else { stackNdx = mTasks.size(); - if (!mService.isCurrentProfileLocked(task.mUserId)) { + if (!showForAllUsers && !mService.isCurrentProfileLocked(task.mUserId)) { // Place the task below all current user tasks. while (--stackNdx >= 0) { - if (!mService.isCurrentProfileLocked(mTasks.get(stackNdx).mUserId)) { + final Task tmpTask = mTasks.get(stackNdx); + if (!tmpTask.showForAllUsers() + || !mService.isCurrentProfileLocked(tmpTask.mUserId)) { break; } } @@ -194,7 +312,7 @@ public class TaskStack { if (toTop) { mDisplayContent.moveStack(this, true); } - EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx); + EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, stackNdx); } void moveTaskToTop(Task task) { @@ -224,6 +342,13 @@ public class TaskStack { } mDisplayContent.layoutNeeded = true; } + for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) { + final AppWindowToken wtoken = mExitingAppTokens.get(appNdx); + if (wtoken.mTask == task) { + wtoken.mIsExiting = false; + mExitingAppTokens.remove(appNdx); + } + } } void attachDisplayContent(DisplayContent displayContent) { @@ -246,7 +371,7 @@ public class TaskStack { for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) { final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows; for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) { - mService.removeWindowInnerLocked(null, appWindows.get(winNdx)); + mService.removeWindowInnerLocked(appWindows.get(winNdx)); doAnotherLayoutPass = true; } } @@ -255,10 +380,8 @@ public class TaskStack { mService.requestTraversalLocked(); } - mAnimationBackgroundSurface.destroySurface(); - mAnimationBackgroundSurface = null; - mDimLayer.destroySurface(); - mDimLayer = null; + close(); + mDisplayContent = null; } @@ -338,18 +461,24 @@ public class TaskStack { void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { // Only set dim params on the highest dimmed layer. - final WindowStateAnimator existingDimWinAnimator = mDimWinAnimator; // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. - if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null - || !existingDimWinAnimator.mSurfaceShown - || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { + if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null + || !mDimWinAnimator.mSurfaceShown + || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { mDimWinAnimator = newWinAnimator; + if (mDimWinAnimator.mWin.mAppToken == null + && !mFullscreen && mDisplayContent != null) { + // Dim should cover the entire screen for system windows. + mDisplayContent.getLogicalDisplayRect(mTmpRect); + mDimLayer.setBounds(mTmpRect); + } } } void stopDimmingIfNeeded() { if (!mDimmingTag && isDimming()) { mDimWinAnimator = null; + mDimLayer.setBounds(mBounds); } } @@ -364,11 +493,11 @@ public class TaskStack { } } - void switchUser(int userId) { + void switchUser() { int top = mTasks.size(); for (int taskNdx = 0; taskNdx < top; ++taskNdx) { Task task = mTasks.get(taskNdx); - if (mService.isCurrentProfileLocked(task.mUserId)) { + if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) { mTasks.remove(taskNdx); mTasks.add(task); --top; @@ -377,8 +506,14 @@ public class TaskStack { } void close() { - mDimLayer.mDimSurface.destroy(); - mAnimationBackgroundSurface.mDimSurface.destroy(); + if (mAnimationBackgroundSurface != null) { + mAnimationBackgroundSurface.destroySurface(); + mAnimationBackgroundSurface = null; + } + if (mDimLayer != null) { + mDimLayer.destroySurface(); + mDimLayer = null; + } } public void dump(String prefix, PrintWriter pw) { @@ -393,7 +528,7 @@ public class TaskStack { } if (mDimLayer.isDimming()) { pw.print(prefix); pw.println("mDimLayer:"); - mDimLayer.printTo(prefix, pw); + mDimLayer.printTo(prefix + " ", pw); pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator); } if (!mExitingAppTokens.isEmpty()) { diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java index e226e3d..ba3ce36 100644 --- a/services/core/java/com/android/server/wm/Watermark.java +++ b/services/core/java/com/android/server/wm/Watermark.java @@ -84,7 +84,7 @@ class Watermark { int fontSize = WindowManagerService.getPropertyInt(tokens, 1, TypedValue.COMPLEX_UNIT_DIP, 20, dm); - mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTextPaint = new Paint(); mTextPaint.setTextSize(fontSize); mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index e833511..52071cc 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -30,8 +30,6 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENT import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING; import android.content.Context; -import android.os.Debug; -import android.os.SystemClock; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -41,6 +39,7 @@ import android.view.SurfaceControl; import android.view.WindowManagerPolicy; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; +import android.view.Choreographer; import com.android.server.wm.WindowManagerService.LayoutFields; @@ -61,9 +60,13 @@ public class WindowAnimator { final Context mContext; final WindowManagerPolicy mPolicy; + /** Is any window animating? */ boolean mAnimating; - final Runnable mAnimationRunnable; + /** Is any app window animating? */ + boolean mAppWindowAnimating; + + final Choreographer.FrameCallback mAnimationFrameCallback; /** Time of current animation step. Reset on each iteration */ long mCurrentTime; @@ -78,9 +81,6 @@ public class WindowAnimator { * seen. If multiple windows satisfy this, use the lowest window. */ WindowState mWindowDetachedWallpaper = null; - WindowStateAnimator mUniverseBackground = null; - int mAboveUniverseLayer = 0; - int mBulkUpdateParams = 0; Object mLastWindowFreezeSource; @@ -118,12 +118,11 @@ public class WindowAnimator { mContext = service.mContext; mPolicy = service.mPolicy; - mAnimationRunnable = new Runnable() { - @Override - public void run() { + mAnimationFrameCallback = new Choreographer.FrameCallback() { + public void doFrame(long frameTimeNs) { synchronized (mService.mWindowMap) { mService.mAnimationScheduled = false; - animateLocked(); + animateLocked(frameTimeNs); } } }; @@ -149,35 +148,6 @@ public class WindowAnimator { mDisplayContentsAnimators.delete(displayId); } - void hideWallpapersLocked(final WindowState w) { - final WindowState wallpaperTarget = mService.mWallpaperTarget; - final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget; - final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens; - - if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) { - final int numTokens = wallpaperTokens.size(); - for (int i = numTokens - 1; i >= 0; i--) { - final WindowToken token = wallpaperTokens.get(i); - final int numWindows = token.windows.size(); - for (int j = numWindows - 1; j >= 0; j--) { - final WindowState wallpaper = token.windows.get(j); - final WindowStateAnimator winAnimator = wallpaper.mWinAnimator; - if (!winAnimator.mLastHidden) { - winAnimator.hide(); - mService.dispatchWallpaperVisibility(wallpaper, false); - setPendingLayoutChanges(Display.DEFAULT_DISPLAY, - WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); - } - } - if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, - "Hiding wallpaper " + token + " from " + w - + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget - + "\n" + Debug.getCallers(5, " ")); - token.hidden = true; - } - } - } - private void updateAppWindowsLocked(int displayId) { ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks(); for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { @@ -189,13 +159,13 @@ public class WindowAnimator { final AppWindowAnimator appAnimator = tokens.get(tokenNdx).mAppAnimator; final boolean wasAnimating = appAnimator.animation != null && appAnimator.animation != AppWindowAnimator.sDummyAnimation; - if (appAnimator.stepAnimationLocked(mCurrentTime)) { - mAnimating = true; + if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { + mAnimating = mAppWindowAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, - "appToken " + appAnimator.mAppToken + " done"); + "appToken " + appAnimator.mAppToken + " done", displayId); if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + appAnimator.mAppToken); } @@ -208,12 +178,12 @@ public class WindowAnimator { final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; final boolean wasAnimating = appAnimator.animation != null && appAnimator.animation != AppWindowAnimator.sDummyAnimation; - if (appAnimator.stepAnimationLocked(mCurrentTime)) { - mAnimating = true; + if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { + mAnimating = mAppWindowAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, - "exiting appToken " + appAnimator.mAppToken + " done"); + "exiting appToken " + appAnimator.mAppToken + " done", displayId); if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); } @@ -231,9 +201,11 @@ public class WindowAnimator { null : winShowWhenLocked.mAppToken; final boolean hideWhenLocked = !(((win.mIsImWindow || imeTarget == win) && showImeOverKeyguard) - || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken || + || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken + // Show all SHOW_WHEN_LOCKED windows while they're animating + || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.isAnimatingLw() // Show error dialogs over apps that dismiss keyguard. - (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0))); + || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0))); return ((mForceHiding == KEYGUARD_ANIMATING_IN) && (!win.mWinAnimator.isAnimating() || hideWhenLocked)) || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked); @@ -605,11 +577,11 @@ public class WindowAnimator { // This will set mOrientationChangeComplete and cause a pass through layout. setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, - "testTokenMayBeDrawnLocked: freezingScreen"); + "testTokenMayBeDrawnLocked: freezingScreen", displayId); } else { setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, - "testTokenMayBeDrawnLocked"); + "testTokenMayBeDrawnLocked", displayId); // We can now show all of the drawn windows! if (!mService.mOpeningApps.contains(wtoken)) { @@ -624,15 +596,16 @@ public class WindowAnimator { /** Locked on mService.mWindowMap. */ - private void animateLocked() { + private void animateLocked(long frameTimeNs) { if (!mInitialized) { return; } - mCurrentTime = SystemClock.uptimeMillis(); + mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS; mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; boolean wasAnimating = mAnimating; mAnimating = false; + mAppWindowAnimating = false; if (WindowManagerService.DEBUG_WINDOW_TRACE) { Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); } @@ -794,6 +767,7 @@ public class WindowAnimator { } else if (dumpAll) { pw.print(subPrefix); pw.println("no ScreenRotationAnimation "); } + pw.println(); } pw.println(); @@ -814,42 +788,36 @@ public class WindowAnimator { pw.print(prefix); pw.print("mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); } - if (mUniverseBackground != null) { - pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground); - pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer); - } } int getPendingLayoutChanges(final int displayId) { if (displayId < 0) { return 0; } - DisplayContent displayContent = mService.getDisplayContentLocked(displayId); + final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); return (displayContent != null) ? displayContent.pendingLayoutChanges : 0; } void setPendingLayoutChanges(final int displayId, final int changes) { - if (displayId >= 0) { - DisplayContent displayContent = mService.getDisplayContentLocked(displayId); - if (displayContent != null) { - displayContent.pendingLayoutChanges |= changes; - } + if (displayId < 0) { + return; + } + final DisplayContent displayContent = mService.getDisplayContentLocked(displayId); + if (displayContent != null) { + displayContent.pendingLayoutChanges |= changes; } } - void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) { - // Used to track which displays layout changes have been done. - SparseIntArray displays = new SparseIntArray(2); + void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String reason, + final int displayId) { WindowList windows = appAnimator.mAppToken.allAppWindows; for (int i = windows.size() - 1; i >= 0; i--) { - final int displayId = windows.get(i).getDisplayId(); - if (displayId >= 0 && displays.indexOfKey(displayId) < 0) { + if (displayId == windows.get(i).getDisplayId()) { setPendingLayoutChanges(displayId, changes); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats(s, getPendingLayoutChanges(displayId)); + mService.debugLayoutRepeats(reason, getPendingLayoutChanges(displayId)); } - // Keep from processing this display again. - displays.put(displayId, changes); + break; } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e9df96b..6bf68e8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import static android.view.WindowManager.LayoutParams.*; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; @@ -28,9 +29,8 @@ import android.view.IWindowId; import android.view.IWindowSessionCallback; import android.view.WindowContentFrameStats; +import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.app.IBatteryStats; -import com.android.internal.policy.PolicyManager; -import com.android.internal.policy.impl.PhoneWindowManager; import com.android.internal.util.FastPrintWriter; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -39,12 +39,14 @@ import com.android.internal.view.WindowManagerPolicyThread; import com.android.server.AttributeCache; import com.android.server.DisplayThread; import com.android.server.EventLogTags; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.input.InputManagerService; import com.android.server.power.ShutdownThread; +import com.android.server.policy.PhoneWindowManager; import android.Manifest; import android.app.ActivityManagerNative; @@ -65,11 +67,9 @@ import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; @@ -128,7 +128,6 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.View; -import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; @@ -137,7 +136,6 @@ import android.view.WindowManagerPolicy.FakeWindow; import android.view.WindowManagerPolicy.PointerEventListener; import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import android.view.animation.Transformation; import java.io.BufferedWriter; import java.io.DataInputStream; @@ -153,6 +151,7 @@ import java.io.StringWriter; import java.net.Socket; import java.text.DateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -181,7 +180,6 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_CONFIGURATION = false; static final boolean DEBUG_APP_TRANSITIONS = false; static final boolean DEBUG_STARTING_WINDOW = false; - static final boolean DEBUG_REORDER = false; static final boolean DEBUG_WALLPAPER = false; static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER; static final boolean DEBUG_DRAG = false; @@ -284,12 +282,6 @@ public class WindowManagerService extends IWindowManager.Stub // The name of the boot animation service in init.rc. private static final String BOOT_ANIMATION_SERVICE = "bootanim"; - /** Minimum value for attachStack and resizeStack weight value */ - public static final float STACK_WEIGHT_MIN = 0.2f; - - /** Maximum value for attachStack and resizeStack weight value */ - public static final float STACK_WEIGHT_MAX = 0.8f; - static final int UPDATE_FOCUS_NORMAL = 0; static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; static final int UPDATE_FOCUS_PLACING_SURFACES = 2; @@ -346,7 +338,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mLimitedAlphaCompositing; - final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager(); + final WindowManagerPolicy mPolicy = new PhoneWindowManager(); final IActivityManager mActivityManager; @@ -422,7 +414,7 @@ public class WindowManagerService extends IWindowManager.Stub * This is set when we have run out of memory, and will either be an empty * list or contain windows that need to be force removed. */ - ArrayList<WindowState> mForceRemoves; + final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); /** * Windows that clients are waiting to have drawn. @@ -564,6 +556,10 @@ public class WindowManagerService extends IWindowManager.Stub WindowState mInputMethodWindow = null; final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); + /** Temporary list for comparison. Always clear this after use so we don't end up with + * orphaned windows references */ + final ArrayList<WindowState> mTmpWindows = new ArrayList<>(); + boolean mHardKeyboardAvailable; boolean mShowImeWithHardKeyboard; OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; @@ -593,7 +589,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); + private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); // If non-null, this is the currently visible window that is associated // with the wallpaper. @@ -622,13 +618,19 @@ public class WindowManagerService extends IWindowManager.Stub static final long WALLPAPER_TIMEOUT_RECOVERY = 10000; boolean mAnimateWallpaperWithTarget; - // We give a wallpaper up to 1000ms to finish drawing before playing app transitions. - static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 1000; + // We give a wallpaper up to 500ms to finish drawing before playing app transitions. + static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 500; static final int WALLPAPER_DRAW_NORMAL = 0; static final int WALLPAPER_DRAW_PENDING = 1; static final int WALLPAPER_DRAW_TIMEOUT = 2; int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL; + // Set to the wallpaper window we would like to hide once the transition animations are done. + // This is useful in cases where we don't want the wallpaper to be hidden when the close app + // is a wallpaper target and is done animating out, but the opening app isn't a wallpaper + // target and isn't done animating in. + WindowState mDeferredHideWallpaper = null; + AppWindowToken mFocusedApp = null; PowerManager mPowerManager; @@ -703,17 +705,22 @@ public class WindowManagerService extends IWindowManager.Stub final WindowAnimator mAnimator; - SparseArray<Task> mTaskIdToTask = new SparseArray<Task>(); + SparseArray<Task> mTaskIdToTask = new SparseArray<>(); /** All of the TaskStacks in the window manager, unordered. For an ordered list call * DisplayContent.getStacks(). */ - SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>(); + SparseArray<TaskStack> mStackIdToStack = new SparseArray<>(); private final PointerEventDispatcher mPointerEventDispatcher; private WindowContentFrameStats mTempWindowRenderStats; final class DragInputEventReceiver extends InputEventReceiver { + // Set, if stylus button was down at the start of the drag. + private boolean mStylusButtonDownAtStart; + // Indicates the first event to check for button state. + private boolean mIsStartEvent = true; + public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); } @@ -729,6 +736,18 @@ public class WindowManagerService extends IWindowManager.Stub boolean endDrag = false; final float newX = motionEvent.getRawX(); final float newY = motionEvent.getRawY(); + final boolean isStylusButtonDown = + (motionEvent.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) + && (motionEvent.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0; + + if (mIsStartEvent) { + if (isStylusButtonDown) { + // First event and the button was down, check for the button being + // lifted in the future, if that happens we'll drop the item. + mStylusButtonDownAtStart = true; + } + mIsStartEvent = false; + } switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: { @@ -738,9 +757,17 @@ public class WindowManagerService extends IWindowManager.Stub } break; case MotionEvent.ACTION_MOVE: { - synchronized (mWindowMap) { - // move the surface and tell the involved window(s) where we are - mDragState.notifyMoveLw(newX, newY); + if (mStylusButtonDownAtStart && !isStylusButtonDown) { + if (DEBUG_DRAG) Slog.d(TAG, "Button no longer pressed; dropping at " + + newX + "," + newY); + synchronized (mWindowMap) { + endDrag = mDragState.notifyDropLw(newX, newY); + } + } else { + synchronized (mWindowMap) { + // move the surface and tell the involved window(s) where we are + mDragState.notifyMoveLw(newX, newY); + } } } break; @@ -764,6 +791,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { mDragState.endDragLw(); } + mStylusButtonDownAtStart = false; + mIsStartEvent = true; } handled = true; @@ -802,6 +831,35 @@ public class WindowManagerService extends IWindowManager.Stub // For example, when this flag is true, there will be no wallpaper service. final boolean mOnlyCore; + /** Listener to notify activity manager about app transitions. */ + private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier + = new WindowManagerInternal.AppTransitionListener() { + + @Override + public void onAppTransitionFinishedLocked(IBinder token) { + AppWindowToken atoken = findAppWindowToken(token); + if (atoken == null) { + return; + } + if (atoken.mLaunchTaskBehind) { + try { + mActivityManager.notifyLaunchTaskBehindComplete(atoken.token); + } catch (RemoteException e) { + } + atoken.mLaunchTaskBehind = false; + } else { + atoken.updateReportedVisibilityLocked(); + if (atoken.mEnteringAnimation) { + atoken.mEnteringAnimation = false; + try { + mActivityManager.notifyEnterAnimationComplete(atoken.token); + } catch (RemoteException e) { + } + } + } + } + }; + public static WindowManagerService main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, @@ -824,9 +882,6 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); - mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer() - * TYPE_LAYER_MULTIPLIER - + TYPE_LAYER_OFFSET; } }, 0); } @@ -885,6 +940,7 @@ public class WindowManagerService extends IWindowManager.Stub mScreenFrozenLock.setReferenceCounted(false); mAppTransition = new AppTransition(context, mH); + mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); mActivityManager = ActivityManagerNative.getDefault(); mBatteryStats = BatteryStatsService.getService(); @@ -1719,7 +1775,7 @@ public class WindowManagerService extends IWindowManager.Stub return true; } - final boolean isWallpaperVisible(WindowState wallpaperTarget) { + private boolean isWallpaperVisible(WindowState wallpaperTarget) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured=" + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??") + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null) @@ -1733,10 +1789,42 @@ public class WindowManagerService extends IWindowManager.Stub || mLowerWallpaperTarget != null; } - static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; - static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; + void hideWallpapersLocked(final WindowState winGoingAway) { + if (mWallpaperTarget != null + && (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) { + return; + } + if (mAppTransition.isRunning()) { + // Defer hiding the wallpaper when app transition is running until the animations + // are done. + mDeferredHideWallpaper = winGoingAway; + return; + } - int adjustWallpaperWindowsLocked() { + final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway); + for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) { + final WindowToken token = mWallpaperTokens.get(i); + for (int j = token.windows.size() - 1; j >= 0; j--) { + final WindowState wallpaper = token.windows.get(j); + final WindowStateAnimator winAnimator = wallpaper.mWinAnimator; + if (!winAnimator.mLastHidden || wasDeferred) { + winAnimator.hide(); + dispatchWallpaperVisibility(wallpaper, false); + final DisplayContent displayContent = wallpaper.getDisplayContent(); + if (displayContent != null) { + displayContent.pendingLayoutChanges |= + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + } + } + } + if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token + + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower=" + + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " ")); + token.hidden = true; + } + } + + boolean adjustWallpaperWindowsLocked() { mInnerFields.mWallpaperMayChange = false; boolean targetChanged = false; @@ -1915,7 +2003,7 @@ public class WindowManagerService extends IWindowManager.Stub // AND any starting window associated with it, AND below the // maximum layer the policy allows for wallpapers. while (foundI > 0) { - WindowState wb = windows.get(foundI-1); + WindowState wb = windows.get(foundI - 1); if (wb.mBaseLayer < maxLayer && wb.mAttachedWindow != foundW && (foundW.mAttachedWindow == null || @@ -1941,7 +2029,7 @@ public class WindowManagerService extends IWindowManager.Stub } else { // Okay i is the position immediately above the wallpaper. Look at // what is below it for later. - foundW = foundI > 0 ? windows.get(foundI-1) : null; + foundW = foundI > 0 ? windows.get(foundI - 1) : null; } if (visible) { @@ -1963,44 +2051,37 @@ public class WindowManagerService extends IWindowManager.Stub // Start stepping backwards from here, ensuring that our wallpaper windows // are correctly placed. - int changed = 0; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); + boolean changed = false; + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + WindowToken token = mWallpaperTokens.get(curTokenNdx); if (token.hidden == visible) { if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "Wallpaper token " + token + " hidden=" + !visible); - changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; token.hidden = !visible; - // Need to do a layout to ensure the wallpaper now has the - // correct size. + // Need to do a layout to ensure the wallpaper now has the correct size. getDefaultDisplayContentLocked().layoutNeeded = true; } - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); + final WindowList tokenWindows = token.windows; + for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { + WindowState wallpaper = tokenWindows.get(wallpaperNdx); if (visible) { updateWallpaperOffsetLocked(wallpaper, dw, dh, false); } - // First, make sure the client has the current visibility - // state. + // First, make sure the client has the current visibility state. dispatchWallpaperVisibility(wallpaper, visible); - wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment; + wallpaper.mWinAnimator.mAnimLayer = + wallpaper.mLayer + mWallpaperAnimLayerAdjustment; if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win " + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); - // First, if this window is at the current index, then all - // is well. + // First, if this window is at the current index, then all is well. if (wallpaper == foundW) { foundI--; - foundW = foundI > 0 - ? windows.get(foundI-1) : null; + foundW = foundI > 0 ? windows.get(foundI - 1) : null; continue; } @@ -2036,52 +2117,24 @@ public class WindowManagerService extends IWindowManager.Stub windows.add(insertionIndex, wallpaper); mWindowsChanged = true; - changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; - } - } - - /* - final TaskStack targetStack = - mWallpaperTarget == null ? null : mWallpaperTarget.getStack(); - if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 && - targetStack != null && !targetStack.isHomeStack()) { - // If the wallpaper target is not on the home stack then make sure that all windows - // from other non-home stacks are above the wallpaper. - for (i = foundI - 1; i >= 0; --i) { - WindowState win = windows.get(i); - if (!win.isVisibleLw()) { - continue; - } - final TaskStack winStack = win.getStack(); - if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) { - windows.remove(i); - windows.add(foundI + 1, win); - } + changed = true; } } - */ - if (targetChanged && DEBUG_WALLPAPER_LIGHT) { - Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget - + " lower=" + mLowerWallpaperTarget + " upper=" - + mUpperWallpaperTarget); - } + if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target=" + + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper=" + + mUpperWallpaperTarget); return changed; } void setWallpaperAnimLayerAdjustmentLocked(int adj) { - if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, - "Setting wallpaper layer adj to " + adj); + if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj); mWallpaperAnimLayerAdjustment = adj; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + WindowList windows = mWallpaperTokens.get(curTokenNdx).windows; + for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { + WindowState wallpaper = windows.get(wallpaperNdx); wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj; if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win " + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer); @@ -2215,14 +2268,10 @@ public class WindowManagerService extends IWindowManager.Stub } } - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + WindowList windows = mWallpaperTokens.get(curTokenNdx).windows; + for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { + WindowState wallpaper = windows.get(wallpaperNdx); if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) { WindowStateAnimator winAnimator = wallpaper.mWinAnimator; winAnimator.computeShownFrameLocked(); @@ -2237,12 +2286,15 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Check wallpaper for visiblity change and notify window if so. + * Check wallpaper for visibility change and notify window if so. * @param wallpaper The wallpaper to test and notify. * @param visible Current visibility. */ void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) { - if (wallpaper.mWallpaperVisible != visible) { + // Only send notification if the visibility actually changed and we are not trying to hide + // the wallpaper when we are deferring hiding of the wallpaper. + if (wallpaper.mWallpaperVisible != visible + && (mDeferredHideWallpaper == null || visible)) { wallpaper.mWallpaperVisible = visible; try { if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, @@ -2254,7 +2306,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - void updateWallpaperVisibilityLocked() { + private void updateWallpaperVisibilityLocked() { final boolean visible = isWallpaperVisible(mWallpaperTarget); final DisplayContent displayContent = mWallpaperTarget.getDisplayContent(); if (displayContent == null) { @@ -2264,21 +2316,18 @@ public class WindowManagerService extends IWindowManager.Stub final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + WindowToken token = mWallpaperTokens.get(curTokenNdx); if (token.hidden == visible) { token.hidden = !visible; // Need to do a layout to ensure the wallpaper now has the // correct size. - getDefaultDisplayContentLocked().layoutNeeded = true; + displayContent.layoutNeeded = true; } - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); + final WindowList windows = token.windows; + for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { + WindowState wallpaper = windows.get(wallpaperNdx); if (visible) { updateWallpaperOffsetLocked(wallpaper, dw, dh, false); } @@ -2299,7 +2348,6 @@ public class WindowManagerService extends IWindowManager.Stub boolean reportNewConfig = false; WindowState attachedWindow = null; - WindowState win = null; long origId; final int type = attrs.type; @@ -2436,7 +2484,7 @@ public class WindowManagerService extends IWindowManager.Stub addToken = true; } - win = new WindowState(this, session, client, token, + WindowState win = new WindowState(this, session, client, token, attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent); if (win.mDeathRecipient == null) { // Client has apparently died, so there is no reason to @@ -2614,11 +2662,11 @@ public class WindowManagerService extends IWindowManager.Stub if (win == null) { return; } - removeWindowLocked(session, win); + removeWindowLocked(win); } } - public void removeWindowLocked(Session session, WindowState win) { + void removeWindowLocked(WindowState win) { if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win); } @@ -2692,7 +2740,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - removeWindowInnerLocked(session, win); + removeWindowInnerLocked(win); // Removing a visible window will effect the computed orientation // So just update orientation if needed. if (wasVisible && updateOrientationFromAppTokensLocked(false)) { @@ -2702,7 +2750,7 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); } - void removeWindowInnerLocked(Session session, WindowState win) { + void removeWindowInnerLocked(WindowState win) { if (win.mRemoved) { // Nothing to do. return; @@ -2712,7 +2760,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowState cwin = win.mChildWindows.get(i); Slog.w(TAG, "Force-removing child win " + cwin + " from container " + win); - removeWindowInnerLocked(cwin.mSession, cwin); + removeWindowInnerLocked(cwin); } win.mRemoved = true; @@ -2936,14 +2984,10 @@ public class WindowManagerService extends IWindowManager.Stub if (window == mWallpaperTarget || window == mLowerWallpaperTarget || window == mUpperWallpaperTarget) { boolean doWait = sync; - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows; + for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) { + WindowState wallpaper = windows.get(wallpaperNdx); try { wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync); @@ -2962,37 +3006,6 @@ public class WindowManagerService extends IWindowManager.Stub return null; } - public void setUniverseTransformLocked(WindowState window, float alpha, - float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) { - Transformation transform = window.mWinAnimator.mUniverseTransform; - transform.setAlpha(alpha); - Matrix matrix = transform.getMatrix(); - matrix.getValues(mTmpFloats); - mTmpFloats[Matrix.MTRANS_X] = offx; - mTmpFloats[Matrix.MTRANS_Y] = offy; - mTmpFloats[Matrix.MSCALE_X] = dsdx; - mTmpFloats[Matrix.MSKEW_Y] = dtdx; - mTmpFloats[Matrix.MSKEW_X] = dsdy; - mTmpFloats[Matrix.MSCALE_Y] = dtdy; - matrix.setValues(mTmpFloats); - final DisplayContent displayContent = window.getDisplayContent(); - if (displayContent == null) { - return; - } - - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - final RectF dispRect = new RectF(0, 0, - displayInfo.logicalWidth, displayInfo.logicalHeight); - matrix.mapRect(dispRect); - window.mGivenTouchableRegion.set(0, 0, - displayInfo.logicalWidth, displayInfo.logicalHeight); - window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, - (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); - window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; - displayContent.layoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - } - public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { synchronized (mWindowMap) { if (mAccessibilityController != null) { @@ -3417,6 +3430,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowState win = atoken.findMainWindow(); Rect containingFrame = new Rect(0, 0, width, height); Rect contentInsets = new Rect(); + Rect appFrame = new Rect(0, 0, width, height); boolean isFullScreen = true; if (win != null) { if (win.mContainingFrame != null) { @@ -3425,6 +3439,9 @@ public class WindowManagerService extends IWindowManager.Stub if (win.mContentInsets != null) { contentInsets.set(win.mContentInsets); } + if (win.mFrame != null) { + appFrame.set(win.mFrame); + } isFullScreen = ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) || @@ -3438,8 +3455,8 @@ public class WindowManagerService extends IWindowManager.Stub enter = false; } Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height, - mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen, - isVoiceInteraction); + mCurConfiguration.orientation, containingFrame, contentInsets, appFrame, + isFullScreen, isVoiceInteraction); if (a != null) { if (DEBUG_ANIM) { RuntimeException e = null; @@ -3625,13 +3642,13 @@ public class WindowManagerService extends IWindowManager.Stub false /*updateInputWindows*/); } - if (delayed) { - if (displayContent != null) { - displayContent.mExitingTokens.add(wtoken); - } + if (delayed && displayContent != null) { + displayContent.mExitingTokens.add(wtoken); } else if (wtoken.windowType == TYPE_WALLPAPER) { mWallpaperTokens.remove(wtoken); } + } else if (wtoken.windowType == TYPE_WALLPAPER) { + mWallpaperTokens.remove(wtoken); } mInputMonitor.updateInputWindowsLw(true /*force*/); @@ -3642,23 +3659,23 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); } - private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) { - if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId + private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken) { + if (DEBUG_STACK) Slog.i(TAG, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId + " atoken=" + atoken); final TaskStack stack = mStackIdToStack.get(stackId); if (stack == null) { throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); } EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); - Task task = new Task(atoken, stack, userId); + Task task = new Task(taskId, stack, userId, this); mTaskIdToTask.put(taskId, task); - stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */); + stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers); return task; } @Override public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, - int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, + int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "addAppToken()")) { @@ -3687,9 +3704,8 @@ public class WindowManagerService extends IWindowManager.Stub } atoken = new AppWindowToken(this, token, voiceInteraction); atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; - atoken.groupId = taskId; atoken.appFullscreen = fullscreen; - atoken.showWhenLocked = showWhenLocked; + atoken.showForAllUsers = showForAllUsers; atoken.requestedOrientation = requestedOrientation; atoken.layoutConfigChanges = (configChanges & (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; @@ -3699,10 +3715,9 @@ public class WindowManagerService extends IWindowManager.Stub Task task = mTaskIdToTask.get(taskId); if (task == null) { - createTask(taskId, stackId, userId, atoken); - } else { - task.addAppToken(addPos, atoken); + task = createTaskLocked(taskId, stackId, userId, atoken); } + task.addAppToken(addPos, atoken); mTokenMap.put(token.asBinder(), atoken); @@ -3715,28 +3730,27 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void setAppGroupId(IBinder token, int groupId) { + public void setAppTask(IBinder token, int taskId) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, - "setAppGroupId()")) { + "setAppTask()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } synchronized(mWindowMap) { final AppWindowToken atoken = findAppWindowToken(token); if (atoken == null) { - Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token); + Slog.w(TAG, "Attempted to set task id of non-existing app token: " + token); return; } - final Task oldTask = mTaskIdToTask.get(atoken.groupId); + final Task oldTask = atoken.mTask; oldTask.removeAppToken(atoken); - atoken.groupId = groupId; - Task newTask = mTaskIdToTask.get(groupId); + Task newTask = mTaskIdToTask.get(taskId); if (newTask == null) { - newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); - } else { - newTask.mAppTokens.add(atoken); + newTask = + createTaskLocked(taskId, oldTask.mStack.mStackId, oldTask.mUserId, atoken); } + newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken); } } @@ -3755,10 +3769,8 @@ public class WindowManagerService extends IWindowManager.Stub } else { // TODO(multidisplay): Change to the correct display. final WindowList windows = getDefaultWindowListLocked(); - int pos = windows.size() - 1; - while (pos >= 0) { + for (int pos = windows.size() - 1; pos >= 0; --pos) { WindowState win = windows.get(pos); - pos--; if (win.mAppToken != null) { // We hit an application window. so the orientation will be determined by the // app window. No point in continuing further. @@ -3858,14 +3870,12 @@ public class WindowManagerService extends IWindowManager.Stub // to use the orientation behind it, then just take whatever // orientation it has and ignores whatever is under it. lastFullscreen = atoken.appFullscreen; - if (lastFullscreen - && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { + if (lastFullscreen && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken + " -- full screen, return " + or); return or; } - // If this application has requested an explicit orientation, - // then use it. + // If this application has requested an explicit orientation, then use it. if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) { if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken @@ -3904,6 +3914,9 @@ public class WindowManagerService extends IWindowManager.Stub private Configuration updateOrientationFromAppTokensLocked( Configuration currentConfig, IBinder freezeThisOneIfNeeded) { + if (!mDisplayReady) { + return null; + } Configuration config = null; if (updateOrientationFromAppTokensLocked(false)) { @@ -3922,20 +3935,19 @@ public class WindowManagerService extends IWindowManager.Stub // the value of the previous configuration. mTempConfiguration.setToDefaults(); mTempConfiguration.fontScale = currentConfig.fontScale; - if (computeScreenConfigurationLocked(mTempConfiguration)) { - if (currentConfig.diff(mTempConfiguration) != 0) { - mWaitingForConfig = true; - final DisplayContent displayContent = getDefaultDisplayContentLocked(); - displayContent.layoutNeeded = true; - int anim[] = new int[2]; - if (displayContent.isDimming()) { - anim[0] = anim[1] = 0; - } else { - mPolicy.selectRotationAnimationLw(anim); - } - startFreezingDisplayLocked(false, anim[0], anim[1]); - config = new Configuration(mTempConfiguration); + computeScreenConfigurationLocked(mTempConfiguration); + if (currentConfig.diff(mTempConfiguration) != 0) { + mWaitingForConfig = true; + final DisplayContent displayContent = getDefaultDisplayContentLocked(); + displayContent.layoutNeeded = true; + int anim[] = new int[2]; + if (displayContent.isDimming()) { + anim[0] = anim[1] = 0; + } else { + mPolicy.selectRotationAnimationLw(anim); } + startFreezingDisplayLocked(false, anim[0], anim[1]); + config = new Configuration(mTempConfiguration); } } @@ -4046,7 +4058,7 @@ public class WindowManagerService extends IWindowManager.Stub void setFocusedStackFrame() { final TaskStack stack; if (mFocusedApp != null) { - Task task = mTaskIdToTask.get(mFocusedApp.groupId); + final Task task = mFocusedApp.mTask; stack = task.mStack; final DisplayContent displayContent = task.getDisplayContent(); if (displayContent != null) { @@ -4055,20 +4067,7 @@ public class WindowManagerService extends IWindowManager.Stub } else { stack = null; } - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame"); - SurfaceControl.openTransaction(); - try { - if (stack == null) { - mFocusedStackFrame.setVisibility(false); - } else { - mFocusedStackFrame.setBounds(stack); - final boolean multipleStacks = !stack.isFullscreen(); - mFocusedStackFrame.setVisibility(multipleStacks); - } - } finally { - SurfaceControl.closeTransaction(); - if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame"); - } + mFocusedStackFrame.setVisibility(stack); } @Override @@ -4179,6 +4178,15 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public void overridePendingAppTransitionClipReveal(int startX, int startY, + int startWidth, int startHeight) { + synchronized(mWindowMap) { + mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth, + startHeight); + } + } + + @Override public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY, IRemoteCallback startedCallback, boolean scaleUp) { synchronized(mWindowMap) { @@ -4212,8 +4220,8 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized(mWindowMap) { - if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition, - new RuntimeException("here").fillInStackTrace()); + if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition + + " Callers=" + Debug.getCallers(5)); if (mAppTransition.isTransitionSet()) { mAppTransition.setReady(); final long origId = Binder.clearCallingIdentity(); @@ -4649,8 +4657,12 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible + "): " + mAppTransition + " hidden=" + wtoken.hidden + " hiddenRequested=" + - wtoken.hiddenRequested, HIDE_STACK_CRAWLS ? - null : new RuntimeException("here").fillInStackTrace()); + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6)); + + mOpeningApps.remove(wtoken); + mClosingApps.remove(wtoken); + wtoken.waitingToShow = wtoken.waitingToHide = false; + wtoken.hiddenRequested = !visible; mOpeningApps.remove(wtoken); mClosingApps.remove(wtoken); @@ -4843,17 +4855,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - void removeAppFromTaskLocked(AppWindowToken wtoken) { - wtoken.removeAllWindows(); - - final Task task = mTaskIdToTask.get(wtoken.groupId); - if (task != null) { - if (!task.removeAppToken(wtoken)) { - Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found."); - } - } - } - @Override public void removeAppToken(IBinder token) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, @@ -4888,20 +4889,20 @@ public class WindowManagerService extends IWindowManager.Stub + " animating=" + wtoken.mAppAnimator.animating); if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: " + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); - final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack; + final TaskStack stack = wtoken.mTask.mStack; if (delayed && !wtoken.allAppWindows.isEmpty()) { // set the token aside because it has an active animation to be finished if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken make exiting: " + wtoken); stack.mExitingAppTokens.add(wtoken); - wtoken.mDeferRemoval = true; + wtoken.mIsExiting = true; } else { // Make sure there is no animation running on this token, // so any windows associated with it will be removed as // soon as their animations are complete wtoken.mAppAnimator.clearAnimation(); wtoken.mAppAnimator.animating = false; - removeAppFromTaskLocked(wtoken); + wtoken.removeAppFromTaskLocked(); } wtoken.removed = true; @@ -4944,39 +4945,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - private boolean tmpRemoveAppWindowsLocked(WindowToken token) { - WindowList windows = token.windows; - final int NW = windows.size(); - if (NW > 0) { - mWindowsChanged = true; - } - int targetDisplayId = -1; - Task targetTask = mTaskIdToTask.get(token.appWindowToken.groupId); - if (targetTask != null) { - DisplayContent targetDisplayContent = targetTask.getDisplayContent(); - if (targetDisplayContent != null) { - targetDisplayId = targetDisplayContent.getDisplayId(); - } - } - for (int i = 0; i < NW; i++) { - WindowState win = windows.get(i); - if (targetDisplayId != -1 && win.getDisplayId() != targetDisplayId) { - continue; - } - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win); - win.getWindowList().remove(win); - int j = win.mChildWindows.size(); - while (j > 0) { - j--; - WindowState cwin = win.mChildWindows.get(j); - if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, - "Tmp removing child window " + cwin); - cwin.getWindowList().remove(cwin); - } - } - return NW > 0; - } - void dumpAppTokensLocked() { final int numStacks = mStackIdToStack.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { @@ -4986,7 +4954,7 @@ public class WindowManagerService extends IWindowManager.Stub final int numTasks = tasks.size(); for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { final Task task = tasks.get(taskNdx); - Slog.v(TAG, " Task #" + task.taskId + " activities from bottom to top:"); + Slog.v(TAG, " Task #" + task.mTaskId + " activities from bottom to top:"); AppTokenList tokens = task.mAppTokens; final int numTokens = tokens.size(); for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { @@ -5008,90 +4976,20 @@ public class WindowManagerService extends IWindowManager.Stub } } - private int findAppWindowInsertionPointLocked(AppWindowToken target) { - final int taskId = target.groupId; - Task targetTask = mTaskIdToTask.get(taskId); - if (targetTask == null) { - Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId=" - + taskId); - return 0; - } - DisplayContent displayContent = targetTask.getDisplayContent(); - if (displayContent == null) { - Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target); - return 0; - } - final WindowList windows = displayContent.getWindowList(); - final int NW = windows.size(); - - boolean found = false; - final ArrayList<Task> tasks = displayContent.getTasks(); - for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { - final Task task = tasks.get(taskNdx); - if (!found && task.taskId != taskId) { - continue; - } - AppTokenList tokens = task.mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - if (!found && wtoken == target) { - found = true; - } - if (found) { - // Find the first app token below the new position that has - // a window displayed. - if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token); - if (wtoken.sendingToBottom) { - if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom"); - continue; - } - for (int i = wtoken.windows.size() - 1; i >= 0; --i) { - WindowState win = wtoken.windows.get(i); - for (int j = win.mChildWindows.size() - 1; j >= 0; --j) { - WindowState cwin = win.mChildWindows.get(j); - if (cwin.mSubLayer >= 0) { - for (int pos = NW - 1; pos >= 0; pos--) { - if (windows.get(pos) == cwin) { - if (DEBUG_REORDER) Slog.v(TAG, - "Found child win @" + (pos + 1)); - return pos + 1; - } - } - } - } - for (int pos = NW - 1; pos >= 0; pos--) { - if (windows.get(pos) == win) { - if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1)); - return pos + 1; - } - } - } - } - } - } - // Never put an app window underneath wallpaper. - for (int pos = NW - 1; pos >= 0; pos--) { - if (windows.get(pos).mIsWallpaper) { - if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos); - return pos + 1; - } - } - return 0; - } - private final int reAddWindowLocked(int index, WindowState win) { final WindowList windows = win.getWindowList(); + // Adding child windows relies on mChildWindows being ordered by mSubLayer. final int NCW = win.mChildWindows.size(); - boolean added = false; + boolean winAdded = false; for (int j=0; j<NCW; j++) { WindowState cwin = win.mChildWindows.get(j); - if (!added && cwin.mSubLayer >= 0) { + if (!winAdded && cwin.mSubLayer >= 0) { if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at " + index + ": " + cwin); win.mRebuilding = false; windows.add(index, win); index++; - added = true; + winAdded = true; } if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " + index + ": " + cwin); @@ -5099,7 +4997,7 @@ public class WindowManagerService extends IWindowManager.Stub windows.add(index, cwin); index++; } - if (!added) { + if (!winAdded) { if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at " + index + ": " + win); win.mRebuilding = false; @@ -5124,41 +5022,40 @@ public class WindowManagerService extends IWindowManager.Stub return index; } - void tmpRemoveTaskWindowsLocked(Task task) { - AppTokenList tokens = task.mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { - tmpRemoveAppWindowsLocked(tokens.get(tokenNdx)); - } - } void moveStackWindowsLocked(DisplayContent displayContent) { - // First remove all of the windows from the list. - final ArrayList<Task> tasks = displayContent.getTasks(); - final int numTasks = tasks.size(); - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - tmpRemoveTaskWindowsLocked(tasks.get(taskNdx)); - } + final WindowList windows = displayContent.getWindowList(); + mTmpWindows.addAll(windows); - // And now add them back at the correct place. - // Where to start adding? - for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { - AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - final int numTokens = tokens.size(); - if (numTokens == 0) { - continue; - } - int pos = findAppWindowInsertionPointLocked(tokens.get(0)); - for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { - final AppWindowToken wtoken = tokens.get(tokenNdx); - if (wtoken != null) { - final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); - if (newPos != pos) { - displayContent.layoutNeeded = true; - } - pos = newPos; - } + rebuildAppWindowListLocked(displayContent); + + // Set displayContent.layoutNeeded if window order changed. + final int tmpSize = mTmpWindows.size(); + final int winSize = windows.size(); + int tmpNdx = 0, winNdx = 0; + while (tmpNdx < tmpSize && winNdx < winSize) { + // Skip over all exiting windows, they've been moved out of order. + WindowState tmp; + do { + tmp = mTmpWindows.get(tmpNdx++); + } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting); + + WindowState win; + do { + win = windows.get(winNdx++); + } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting); + + if (tmp != win) { + // Window order changed. + displayContent.layoutNeeded = true; + break; } } + if (tmpNdx != winNdx) { + // One list was different from the other. + displayContent.layoutNeeded = true; + } + mTmpWindows.clear(); if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/)) { @@ -5281,30 +5178,6 @@ public class WindowManagerService extends IWindowManager.Stub mStackIdToStack.remove(stackId); } - void removeTaskLocked(Task task) { - final int taskId = task.taskId; - final TaskStack stack = task.mStack; - if (!task.mAppTokens.isEmpty() && stack.isAnimating()) { - if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId); - task.mDeferRemoval = true; - return; - } - if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId); - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); - task.mDeferRemoval = false; - stack.removeTask(task); - mTaskIdToTask.delete(task.taskId); - - final ArrayList<AppWindowToken> exitingApps = stack.mExitingAppTokens; - for (int appNdx = exitingApps.size() - 1; appNdx >= 0; --appNdx) { - final AppWindowToken wtoken = exitingApps.get(appNdx); - if (wtoken.groupId == taskId) { - wtoken.mDeferRemoval = false; - exitingApps.remove(appNdx); - } - } - } - public void removeTask(int taskId) { synchronized (mWindowMap) { Task task = mTaskIdToTask.get(taskId); @@ -5312,7 +5185,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId); return; } - removeTaskLocked(task); + task.removeLocked(); } } @@ -5322,6 +5195,7 @@ public class WindowManagerService extends IWindowManager.Stub + " to " + (toTop ? "top" : "bottom")); Task task = mTaskIdToTask.get(taskId); if (task == null) { + if (DEBUG_STACK) Slog.i(TAG, "addTask: could not find taskId=" + taskId); return; } TaskStack stack = mStackIdToStack.get(stackId); @@ -5332,7 +5206,33 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void resizeStack(int stackId, Rect bounds) { + public void moveTaskToStack(int taskId, int stackId, boolean toTop) { + synchronized (mWindowMap) { + if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: moving taskId=" + taskId + + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom")); + Task task = mTaskIdToTask.get(taskId); + if (task == null) { + if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find taskId=" + taskId); + return; + } + TaskStack stack = mStackIdToStack.get(stackId); + if (stack == null) { + if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find stackId=" + stackId); + return; + } + task.moveTaskToStack(stack, toTop); + final DisplayContent displayContent = stack.getDisplayContent(); + displayContent.layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + } + } + + /** + * Re-sizes the specified stack and its containing windows. + * Returns a {@link Configuration} object that contains configurations settings + * that should be overridden due to the operation. + */ + public Configuration resizeStack(int stackId, Rect bounds) { synchronized (mWindowMap) { final TaskStack stack = mStackIdToStack.get(stackId); if (stack == null) { @@ -5344,6 +5244,7 @@ public class WindowManagerService extends IWindowManager.Stub stack.getDisplayContent().layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } + return new Configuration(stack.mOverrideConfig); } } @@ -5356,6 +5257,44 @@ public class WindowManagerService extends IWindowManager.Stub bounds.setEmpty(); } + /** Returns the id of an application (non-home stack) stack that match the input bounds. + * -1 if no stack matches.*/ + public int getStackIdWithBounds(Rect bounds) { + Rect stackBounds = new Rect(); + synchronized (mWindowMap) { + for (int i = mStackIdToStack.size() - 1; i >= 0; --i) { + TaskStack stack = mStackIdToStack.valueAt(i); + if (stack.mStackId != HOME_STACK_ID) { + stack.getBounds(stackBounds); + if (stackBounds.equals(bounds)) { + return stack.mStackId; + } + } + } + } + return -1; + } + + /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen. + * Returns a {@link Configuration} object that contains configurations settings + * that should be overridden due to the operation. + */ + public Configuration forceStackToFullscreen(int stackId, boolean forceFullscreen) { + synchronized (mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack == null) { + throw new IllegalArgumentException("resizeStack: stackId " + stackId + + " not found."); + } + if (stack.forceFullscreen(forceFullscreen)) { + stack.resizeWindows(); + stack.getDisplayContent().layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + } + return new Configuration(stack.mOverrideConfig); + } + } + // ------------------------------------------------------------- // Misc IWindowSession methods // ------------------------------------------------------------- @@ -5716,7 +5655,7 @@ public class WindowManagerService extends IWindowManager.Stub final int numDisplays = mDisplayContents.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); - displayContent.switchUserStacks(newUserId); + displayContent.switchUserStacks(); rebuildAppWindowListLocked(displayContent); } performLayoutAndPlaceSurfacesLocked(); @@ -6145,26 +6084,57 @@ public class WindowManagerService extends IWindowManager.Stub * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. * In portrait mode, it grabs the upper region of the screen based on the vertical dimension * of the target image. + */ + @Override + public boolean requestAssistScreenshot(final IAssistScreenshotReceiver receiver) { + if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, + "requestAssistScreenshot()")) { + throw new SecurityException("Requires READ_FRAME_BUFFER permission"); + } + + FgThread.getHandler().post(new Runnable() { + @Override + public void run() { + Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, + true); + try { + receiver.send(bm); + } catch (RemoteException e) { + } + } + }); + + return true; + } + + /** + * Takes a snapshot of the screen. In landscape mode this grabs the whole screen. + * In portrait mode, it grabs the upper region of the screen based on the vertical dimension + * of the target image. * * @param displayId the Display to take a screenshot of. * @param width the width of the target bitmap * @param height the height of the target bitmap - * @param force565 if true the returned bitmap will be RGB_565, otherwise it - * will be the same config as the surface */ @Override - public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, - int height, boolean force565) { + public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) { if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, "screenshotApplications()")) { throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } + return screenshotApplicationsInner(appToken, displayId, width, height, false); + } - final DisplayContent displayContent = getDisplayContentLocked(displayId); - if (displayContent == null) { - if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken - + ": returning null. No Display for displayId=" + displayId); - return null; + Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height, + boolean includeFullDisplay) { + final DisplayContent displayContent; + synchronized(mWindowMap) { + displayContent = getDisplayContentLocked(displayId); + if (displayContent == null) { + if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken + + ": returning null. No Display for displayId=" + displayId); + return null; + } } final DisplayInfo displayInfo = displayContent.getDisplayInfo(); int dw = displayInfo.logicalWidth; @@ -6181,9 +6151,6 @@ public class WindowManagerService extends IWindowManager.Stub final Rect frame = new Rect(); final Rect stackBounds = new Rect(); - float scale = 0; - int rot = Surface.ROTATION_0; - boolean screenshotReady; int minLayer; if (appToken == null) { @@ -6264,7 +6231,7 @@ public class WindowManagerService extends IWindowManager.Stub } // Don't include wallpaper in bounds calculation - if (!ws.mIsWallpaper) { + if (!includeFullDisplay && !ws.mIsWallpaper) { final Rect wf = ws.mFrame; final Rect cr = ws.mContentInsets; int left = wf.left + cr.left; @@ -6318,8 +6285,21 @@ public class WindowManagerService extends IWindowManager.Stub return null; } - // Constrain frame to the screen size. - frame.intersect(0, 0, dw, dh); + if (!includeFullDisplay) { + // Constrain frame to the screen size. + frame.intersect(0, 0, dw, dh); + } else { + // Caller just wants entire display. + frame.set(0, 0, dw, dh); + } + + + if (width < 0) { + width = frame.width(); + } + if (height < 0) { + height = frame.height(); + } // Tell surface flinger what part of the image to crop. Take the top // right part of the application, and crop the larger dimension to fit. @@ -6333,7 +6313,7 @@ public class WindowManagerService extends IWindowManager.Stub } // The screenshot API does not apply the current screen rotation. - rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); + int rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; @@ -6596,13 +6576,12 @@ public class WindowManagerService extends IWindowManager.Stub screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY); - // We need to update our screen size information to match the new - // rotation. Note that this is redundant with the later call to - // sendNewConfiguration() that must be called after this function - // returns... however we need to do the screen size part of that - // before then so we have the correct size to use when initializing - // the rotation animation for the new rotation. - computeScreenConfigurationLocked(null); + // We need to update our screen size information to match the new rotation. If the rotation + // has actually changed then this method will return true and, according to the comment at + // the top of the method, the caller is obligated to call computeNewConfigurationLocked(). + // By updating the Display info here it will be available to + // computeScreenConfigurationLocked later. + updateDisplayAndOrientationLocked(); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); if (!inTransaction) { @@ -7151,9 +7130,11 @@ public class WindowManagerService extends IWindowManager.Stub public Configuration computeNewConfiguration() { synchronized (mWindowMap) { + if (!mDisplayReady) { + return null; + } Configuration config = computeNewConfigurationLocked(); - if (config == null && mWaitingForConfig) { - // Nothing changed but we are waiting for something... stop that! + if (mWaitingForConfig) { mWaitingForConfig = false; mLastFinishedFreezeSource = "new-config"; performLayoutAndPlaceSurfacesLocked(); @@ -7165,9 +7146,7 @@ public class WindowManagerService extends IWindowManager.Stub Configuration computeNewConfigurationLocked() { Configuration config = new Configuration(); config.fontScale = 0; - if (!computeScreenConfigurationLocked(config)) { - return null; - } + computeScreenConfigurationLocked(config); return config; } @@ -7274,11 +7253,8 @@ public class WindowManagerService extends IWindowManager.Stub return sw; } - boolean computeScreenConfigurationLocked(Configuration config) { - if (!mDisplayReady) { - return false; - } - + /** Do not call if mDisplayReady == false */ + DisplayInfo updateDisplayAndOrientationLocked() { // TODO(multidisplay): For now, apply Configuration to main screen only. final DisplayContent displayContent = getDefaultDisplayContentLocked(); @@ -7308,11 +7284,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (config != null) { - config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : - Configuration.ORIENTATION_LANDSCAPE; - } - // Update application display metrics. final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation); final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation); @@ -7327,97 +7298,113 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.getLogicalMetrics(mRealDisplayMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); displayInfo.getAppMetrics(mDisplayMetrics); + if (displayContent.mDisplayScalingDisabled) { + displayInfo.flags |= Display.FLAG_SCALING_DISABLED; + } else { + displayInfo.flags &= ~Display.FLAG_SCALING_DISABLED; + } + mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayContent.getDisplayId(), displayInfo); + displayContent.mBaseDisplayRect.set(0, 0, dw, dh); } if (false) { Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight); } - final DisplayMetrics dm = mDisplayMetrics; - mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, + mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics, mCompatDisplayMetrics); + return displayInfo; + } - if (config != null) { - config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) - / dm.density); - config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) - / dm.density); - computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config); - - config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); - config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); - config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh); - config.densityDpi = displayContent.mBaseDisplayDensity; - - // Update the configuration based on available input devices, lid switch, - // and platform configuration. - config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; - config.keyboard = Configuration.KEYBOARD_NOKEYS; - config.navigation = Configuration.NAVIGATION_NONAV; - - int keyboardPresence = 0; - int navigationPresence = 0; - final InputDevice[] devices = mInputManager.getInputDevices(); - final int len = devices.length; - for (int i = 0; i < len; i++) { - InputDevice device = devices[i]; - if (!device.isVirtual()) { - final int sources = device.getSources(); - final int presenceFlag = device.isExternal() ? - WindowManagerPolicy.PRESENCE_EXTERNAL : - WindowManagerPolicy.PRESENCE_INTERNAL; - - if (mIsTouchDevice) { - if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == - InputDevice.SOURCE_TOUCHSCREEN) { - config.touchscreen = Configuration.TOUCHSCREEN_FINGER; - } - } else { - config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; - } + /** Do not call if mDisplayReady == false */ + void computeScreenConfigurationLocked(Configuration config) { + final DisplayInfo displayInfo = updateDisplayAndOrientationLocked(); - if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { - config.navigation = Configuration.NAVIGATION_TRACKBALL; - navigationPresence |= presenceFlag; - } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD - && config.navigation == Configuration.NAVIGATION_NONAV) { - config.navigation = Configuration.NAVIGATION_DPAD; - navigationPresence |= presenceFlag; + final int dw = displayInfo.logicalWidth; + final int dh = displayInfo.logicalHeight; + config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT : + Configuration.ORIENTATION_LANDSCAPE; + config.screenWidthDp = + (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) / mDisplayMetrics.density); + config.screenHeightDp = + (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) / mDisplayMetrics.density); + final boolean rotated = (mRotation == Surface.ROTATION_90 + || mRotation == Surface.ROTATION_270); + computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, mDisplayMetrics.density, + config); + + config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale); + config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale); + config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, + mDisplayMetrics, dw, dh); + config.densityDpi = displayInfo.logicalDensityDpi; + + // Update the configuration based on available input devices, lid switch, + // and platform configuration. + config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; + config.keyboard = Configuration.KEYBOARD_NOKEYS; + config.navigation = Configuration.NAVIGATION_NONAV; + + int keyboardPresence = 0; + int navigationPresence = 0; + final InputDevice[] devices = mInputManager.getInputDevices(); + final int len = devices.length; + for (int i = 0; i < len; i++) { + InputDevice device = devices[i]; + if (!device.isVirtual()) { + final int sources = device.getSources(); + final int presenceFlag = device.isExternal() ? + WindowManagerPolicy.PRESENCE_EXTERNAL : + WindowManagerPolicy.PRESENCE_INTERNAL; + + if (mIsTouchDevice) { + if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == + InputDevice.SOURCE_TOUCHSCREEN) { + config.touchscreen = Configuration.TOUCHSCREEN_FINGER; } + } else { + config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH; + } - if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { - config.keyboard = Configuration.KEYBOARD_QWERTY; - keyboardPresence |= presenceFlag; - } + if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) { + config.navigation = Configuration.NAVIGATION_TRACKBALL; + navigationPresence |= presenceFlag; + } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD + && config.navigation == Configuration.NAVIGATION_NONAV) { + config.navigation = Configuration.NAVIGATION_DPAD; + navigationPresence |= presenceFlag; } - } - if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { - config.navigation = Configuration.NAVIGATION_DPAD; - navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; + if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) { + config.keyboard = Configuration.KEYBOARD_QWERTY; + keyboardPresence |= presenceFlag; + } } + } - // Determine whether a hard keyboard is available and enabled. - boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; - if (hardKeyboardAvailable != mHardKeyboardAvailable) { - mHardKeyboardAvailable = hardKeyboardAvailable; - mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); - mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); - } - if (mShowImeWithHardKeyboard) { - config.keyboard = Configuration.KEYBOARD_NOKEYS; - } + if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) { + config.navigation = Configuration.NAVIGATION_DPAD; + navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL; + } - // Let the policy update hidden states. - config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; - config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; - config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; - mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); + // Determine whether a hard keyboard is available and enabled. + boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; + if (hardKeyboardAvailable != mHardKeyboardAvailable) { + mHardKeyboardAvailable = hardKeyboardAvailable; + mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); + mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); + } + if (mShowImeWithHardKeyboard) { + config.keyboard = Configuration.KEYBOARD_NOKEYS; } - return true; + // Let the policy update hidden states. + config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; + config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; + config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; + mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence); } public boolean isHardKeyboardAvailable() { @@ -7488,7 +7475,7 @@ public class WindowManagerService extends IWindowManager.Stub outSurface.copyFrom(surface); final IBinder winBinder = window.asBinder(); token = new Binder(); - mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder); + mDragState = new DragState(this, token, surface, flags, winBinder); token = mDragState.mToken = new Binder(); // 5 second timeout for this window to actually begin the drag @@ -7616,7 +7603,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); - readForcedDisplaySizeAndDensityLocked(displayContent); + readForcedDisplayPropertiesLocked(displayContent); mDisplayReady = true; } @@ -8164,16 +8151,16 @@ public class WindowManagerService extends IWindowManager.Stub break; case TAP_OUTSIDE_STACK: { -// int stackId; -// synchronized (mWindowMap) { -// stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); -// } -// if (stackId >= 0) { -// try { -// mActivityManager.setFocusedStack(stackId); -// } catch (RemoteException e) { -// } -// } + int stackId; + synchronized (mWindowMap) { + stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); + } + if (stackId >= 0) { + try { + mActivityManager.setFocusedStack(stackId); + } catch (RemoteException e) { + } + } } break; case NOTIFY_ACTIVITY_DRAWN: @@ -8389,7 +8376,47 @@ public class WindowManagerService extends IWindowManager.Stub } } - private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) { + @Override + public void setForcedDisplayScalingMode(int displayId, int mode) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) != + PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Must hold permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + if (displayId != Display.DEFAULT_DISPLAY) { + throw new IllegalArgumentException("Can only set the default display"); + } + final long ident = Binder.clearCallingIdentity(); + try { + synchronized(mWindowMap) { + final DisplayContent displayContent = getDisplayContentLocked(displayId); + if (displayContent != null) { + if (mode < 0 || mode > 1) { + mode = 0; + } + setForcedDisplayScalingModeLocked(displayContent, mode); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.DISPLAY_SCALING_FORCE, mode); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, + int mode) { + Slog.i(TAG, "Using display scaling mode: " + (mode == 0 ? "auto" : "off")); + + synchronized(displayContent.mDisplaySizeLock) { + displayContent.mDisplayScalingDisabled = (mode != 0); + } + reconfigureDisplayLocked(displayContent); + } + + private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) { + // Display size. String sizeStr = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.DISPLAY_SIZE_FORCED); if (sizeStr == null || sizeStr.length() == 0) { @@ -8414,6 +8441,8 @@ public class WindowManagerService extends IWindowManager.Stub } } } + + // Display density. String densityStr = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.DISPLAY_DENSITY_FORCED); if (densityStr == null || densityStr.length() == 0) { @@ -8432,6 +8461,16 @@ public class WindowManagerService extends IWindowManager.Stub } catch (NumberFormatException ex) { } } + + // Display scaling mode. + int mode = Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DISPLAY_SCALING_FORCE, 0); + if (mode != 0) { + synchronized(displayContent.mDisplaySizeLock) { + Slog.i(TAG, "FORCED DISPLAY SCALING DISABLED"); + displayContent.mDisplayScalingDisabled = true; + } + } } // displayContent must not be null @@ -8564,17 +8603,17 @@ public class WindowManagerService extends IWindowManager.Stub // displayContent must not be null private void reconfigureDisplayLocked(DisplayContent displayContent) { // TODO: Multidisplay: for now only use with default display. + if (!mDisplayReady) { + return; + } configureDisplayPolicyLocked(displayContent); displayContent.layoutNeeded = true; boolean configChanged = updateOrientationFromAppTokensLocked(false); mTempConfiguration.setToDefaults(); mTempConfiguration.fontScale = mCurConfiguration.fontScale; - if (computeScreenConfigurationLocked(mTempConfiguration)) { - if (mCurConfiguration.diff(mTempConfiguration) != 0) { - configChanged = true; - } - } + computeScreenConfigurationLocked(mTempConfiguration); + configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0; if (configChanged) { mWaitingForConfig = true; @@ -8700,7 +8739,7 @@ public class WindowManagerService extends IWindowManager.Stub numRemoved++; continue; } else if (lastBelow == i-1) { - if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { + if (w.mAttrs.type == TYPE_WALLPAPER) { lastBelow = i; } } @@ -8735,7 +8774,7 @@ public class WindowManagerService extends IWindowManager.Stub final int numTokens = tokens.size(); for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) { final AppWindowToken wtoken = tokens.get(tokenNdx); - if (wtoken.mDeferRemoval) { + if (wtoken.mIsExiting) { continue; } i = reAddAppWindowsLocked(displayContent, i, wtoken); @@ -8745,6 +8784,7 @@ public class WindowManagerService extends IWindowManager.Stub i -= lastBelow; if (i != numRemoved) { + displayContent.layoutNeeded = true; Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " + numRemoved + " windows but added " + i, new RuntimeException("here").fillInStackTrace()); @@ -8765,6 +8805,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG, "Final window list:"); dumpWindowsLocked(); } + Arrays.fill(mRebuildTmp, null); } private final void assignLayersLocked(WindowList windows) { @@ -8873,29 +8914,24 @@ public class WindowManagerService extends IWindowManager.Stub Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout"); mInLayout = true; - boolean recoveringMemory = false; - try { - if (mForceRemoves != null) { - recoveringMemory = true; - // Wait a little bit for things to settle down, and off we go. - for (int i=0; i<mForceRemoves.size(); i++) { - WindowState ws = mForceRemoves.get(i); - Slog.i(TAG, "Force removing: " + ws); - removeWindowInnerLocked(ws.mSession, ws); - } - mForceRemoves = null; - Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); - Object tmp = new Object(); - synchronized (tmp) { - try { - tmp.wait(250); - } catch (InterruptedException e) { - } + boolean recoveringMemory = false; + if (!mForceRemoves.isEmpty()) { + recoveringMemory = true; + // Wait a little bit for things to settle down, and off we go. + while (!mForceRemoves.isEmpty()) { + WindowState ws = mForceRemoves.remove(0); + Slog.i(TAG, "Force removing: " + ws); + removeWindowInnerLocked(ws); + } + Slog.w(TAG, "Due to memory failure, waiting a bit for next layout"); + Object tmp = new Object(); + synchronized (tmp) { + try { + tmp.wait(250); + } catch (InterruptedException e) { } } - } catch (RuntimeException e) { - Slog.wtf(TAG, "Unhandled exception while force removing for memory", e); } try { @@ -8953,8 +8989,6 @@ public class WindowManagerService extends IWindowManager.Stub + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); } - WindowStateAnimator universeBackground = null; - mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation); if (isDefaultDisplay) { // Not needed on non-default displays. @@ -9012,8 +9046,7 @@ public class WindowManagerService extends IWindowManager.Stub || ((win.isConfigChanged() || win.setInsetsChanged()) && ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || (win.mHasSurface && win.mAppToken != null && - win.mAppToken.layoutConfigChanges))) - || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { + win.mAppToken.layoutConfigChanges)))) { if (!win.mLayoutAttached) { if (initial) { //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial"); @@ -9037,16 +9070,6 @@ public class WindowManagerService extends IWindowManager.Stub if (topAttached < 0) topAttached = i; } } - if (win.mViewVisibility == View.VISIBLE - && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND - && universeBackground == null) { - universeBackground = win.mWinAnimator; - } - } - - if (mAnimator.mUniverseBackground != universeBackground) { - mFocusMayChange = true; - mAnimator.mUniverseBackground = universeBackground; } boolean attachedBehindDream = false; @@ -9150,6 +9173,7 @@ public class WindowManagerService extends IWindowManager.Stub goodToGo = false; } } + if (goodToGo && isWallpaperVisible(mWallpaperTarget)) { boolean wallpaperGoodToGo = true; for (int curTokenIndex = mWallpaperTokens.size() - 1; @@ -9190,7 +9214,6 @@ public class WindowManagerService extends IWindowManager.Stub if (mSkipAppTransitionAnimation) { transit = AppTransition.TRANSIT_UNSET; } - mAppTransition.goodToGo(); mStartingIconInTransition = false; mSkipAppTransitionAnimation = false; @@ -9343,6 +9366,7 @@ public class WindowManagerService extends IWindowManager.Stub for (int j = 0; j < N; j++) { appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); } + mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); } } @@ -9365,6 +9389,7 @@ public class WindowManagerService extends IWindowManager.Stub appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); } mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); + mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); if (animLp != null) { int layer = -1; @@ -9401,6 +9426,7 @@ public class WindowManagerService extends IWindowManager.Stub if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) { scheduleRemoveStartingWindowLocked(wtoken); } + mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); if (animLp != null) { int layer = -1; @@ -9485,6 +9511,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator); mAppTransition.postAnimationCallback(); mAppTransition.clear(); @@ -9518,6 +9545,12 @@ public class WindowManagerService extends IWindowManager.Stub int changes = 0; mAppTransition.setIdle(); + + if (mDeferredHideWallpaper != null) { + hideWallpapersLocked(mDeferredHideWallpaper); + mDeferredHideWallpaper = null; + } + // Restore window app tokens to the ActivityManager views ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks(); for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { @@ -9614,14 +9647,12 @@ public class WindowManagerService extends IWindowManager.Stub /** * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. - * - * @param w WindowState this method is applied to. - * @param currentTime The time which animations use for calculating transitions. + * @param w WindowState this method is applied to. * @param innerDw Width of app window. * @param innerDh Height of app window. */ - private void handleNotObscuredLocked(final WindowState w, final long currentTime, - final int innerDw, final int innerDh) { + private void handleNotObscuredLocked(final WindowState w, + final int innerDw, final int innerDh) { final WindowManager.LayoutParams attrs = w.mAttrs; final int attrFlags = attrs.flags; final boolean canBeSeen = w.isDisplayedLw(); @@ -9740,8 +9771,6 @@ public class WindowManagerService extends IWindowManager.Stub + Debug.getCallers(3)); } - final long currentTime = SystemClock.uptimeMillis(); - int i; boolean updateInputWindowsNeeded = false; @@ -9832,8 +9861,7 @@ public class WindowManagerService extends IWindowManager.Stub if ((displayContent.pendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 && - (adjustWallpaperWindowsLocked() & - ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { + adjustWallpaperWindowsLocked()) { assignLayersLocked(windows); displayContent.layoutNeeded = true; } @@ -9864,9 +9892,6 @@ public class WindowManagerService extends IWindowManager.Stub // it is animating. displayContent.pendingLayoutChanges = 0; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " - + mLayoutRepeatCount, displayContent.pendingLayoutChanges); - if (isDefaultDisplay) { mPolicy.beginPostLayoutPolicyLw(dw, dh); for (i = windows.size() - 1; i >= 0; i--) { @@ -9901,7 +9926,7 @@ public class WindowManagerService extends IWindowManager.Stub // Update effect. w.mObscured = mInnerFields.mObscured; if (!mInnerFields.mObscured) { - handleNotObscuredLocked(w, currentTime, innerDw, innerDh); + handleNotObscuredLocked(w, innerDw, innerDh); } if (stack != null && !stack.testDimmingTag()) { @@ -9918,18 +9943,20 @@ public class WindowManagerService extends IWindowManager.Stub final WindowStateAnimator winAnimator = w.mWinAnimator; - // If the window has moved due to its containing - // content frame changing, then we'd like to animate - // it. - if (w.mHasSurface && w.shouldAnimateMove()) { - // Frame has moved, containing content frame - // has also moved, and we're not currently animating... - // let's do something. - Animation a = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.window_move_from_decor); - winAnimator.setAnimation(a); - winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; - winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; + // If the window has moved due to its containing content frame changing, then + // notify the listeners and optionally animate it. + if (w.hasMoved()) { + // Frame has moved, containing content frame has also moved, and we're not + // currently animating... let's do something. + final int left = w.mFrame.left; + final int top = w.mFrame.top; + if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0) { + Animation a = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.window_move_from_decor); + winAnimator.setAnimation(a); + winAnimator.mAnimDw = w.mLastFrame.left - left; + winAnimator.mAnimDh = w.mLastFrame.top - top; + } //TODO (multidisplay): Accessibility supported only for the default display. if (mAccessibilityController != null @@ -9938,7 +9965,7 @@ public class WindowManagerService extends IWindowManager.Stub } try { - w.mClient.moved(w.mFrame.left, w.mFrame.top); + w.mClient.moved(left, top); } catch (RemoteException e) { } } @@ -9950,7 +9977,7 @@ public class WindowManagerService extends IWindowManager.Stub if (w.mHasSurface && !w.isHiddenFromUserLocked()) { // Take care of the window being ready to display. final boolean committed = - winAnimator.commitFinishDrawingLocked(currentTime); + winAnimator.commitFinishDrawingLocked(); if (isDefaultDisplay && committed) { if (w.mAttrs.type == TYPE_DREAM) { // HACK: When a dream is shown, it may at that @@ -10075,7 +10102,7 @@ public class WindowManagerService extends IWindowManager.Stub defaultDisplay.pendingLayoutChanges); } - if (!mAnimator.mAnimating && mAppTransition.isRunning()) { + if (!mAnimator.mAppWindowAnimating && mAppTransition.isRunning()) { // We have finished the animation of an app transition. To do // this, we have delayed a lot of operations like showing and // hiding apps, moving apps in Z-order, etc. The app token list @@ -10188,7 +10215,7 @@ public class WindowManagerService extends IWindowManager.Stub for (i = exitingAppTokens.size() - 1; i >= 0; i--) { AppWindowToken token = exitingAppTokens.get(i); if (!token.hasVisible && !mClosingApps.contains(token) && - (!token.mDeferRemoval || token.allAppWindows.isEmpty())) { + (!token.mIsExiting || token.allAppWindows.isEmpty())) { // Make sure there is no animation running on this token, // so any windows associated with it will be removed as // soon as their animations are complete @@ -10196,12 +10223,7 @@ public class WindowManagerService extends IWindowManager.Stub token.mAppAnimator.animating = false; if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "performLayout: App token exiting now removed" + token); - removeAppFromTaskLocked(token); - exitingAppTokens.remove(i); - final Task task = mTaskIdToTask.get(token.groupId); - if (task != null && task.mDeferRemoval && task.mAppTokens.isEmpty()) { - removeTaskLocked(task); - } + token.removeAppFromTaskLocked(); } } } @@ -10287,7 +10309,7 @@ public class WindowManagerService extends IWindowManager.Stub DisplayContentList displayList = new DisplayContentList(); for (i = 0; i < N; i++) { WindowState w = mPendingRemoveTmp[i]; - removeWindowInnerLocked(w.mSession, w); + removeWindowInnerLocked(w); final DisplayContent displayContent = w.getDisplayContent(); if (displayContent != null && !displayList.contains(displayContent)) { displayList.add(displayContent); @@ -10390,8 +10412,7 @@ public class WindowManagerService extends IWindowManager.Stub void scheduleAnimationLocked() { if (!mAnimationScheduled) { mAnimationScheduled = true; - mChoreographer.postCallback( - Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null); + mChoreographer.postFrameCallback(mAnimator.mAnimationFrameCallback); } } @@ -10464,10 +10485,6 @@ public class WindowManagerService extends IWindowManager.Stub EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(), winAnimator.mSession.mPid, operation); - if (mForceRemoves == null) { - mForceRemoves = new ArrayList<WindowState>(); - } - long callingIdentity = Binder.clearCallingIdentity(); try { // There was some problem... first, do a sanity check of the @@ -10627,11 +10644,6 @@ public class WindowManagerService extends IWindowManager.Stub } private WindowState computeFocusedWindowLocked() { - if (mAnimator.mUniverseBackground != null - && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) { - return mAnimator.mUniverseBackground.mWin; - } - final int displayCount = mDisplayContents.size(); for (int i = 0; i < displayCount; i++) { final DisplayContent displayContent = mDisplayContents.valueAt(i); @@ -10654,6 +10666,10 @@ public class WindowManagerService extends IWindowManager.Stub + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys()); + if (!win.canReceiveKeys()) { + continue; + } + AppWindowToken wtoken = win.mAppToken; // If this window's application has been removed, just skip it. @@ -10663,10 +10679,6 @@ public class WindowManagerService extends IWindowManager.Stub continue; } - if (!win.canReceiveKeys()) { - continue; - } - // Descend through all of the app tokens and find the first that either matches // win.mAppToken (return win) or mFocusedApp (return null). if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING && @@ -10822,15 +10834,13 @@ public class WindowManagerService extends IWindowManager.Stub scheduleAnimationLocked(); } else { screenRotationAnimation.kill(); - screenRotationAnimation = null; - mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); + mAnimator.setScreenRotationAnimationLocked(displayId, null); updateRotation = true; } } else { if (screenRotationAnimation != null) { screenRotationAnimation.kill(); - screenRotationAnimation = null; - mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation); + mAnimator.setScreenRotationAnimationLocked(displayId, null); } updateRotation = true; } @@ -11097,7 +11107,7 @@ public class WindowManagerService extends IWindowManager.Stub void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); - if (mTokenMap.size() > 0) { + if (!mTokenMap.isEmpty()) { pw.println(" All tokens:"); Iterator<WindowToken> it = mTokenMap.values().iterator(); while (it.hasNext()) { @@ -11111,7 +11121,7 @@ public class WindowManagerService extends IWindowManager.Stub } } } - if (mWallpaperTokens.size() > 0) { + if (!mWallpaperTokens.isEmpty()) { pw.println(); pw.println(" Wallpaper tokens:"); for (int i=mWallpaperTokens.size()-1; i>=0; i--) { @@ -11126,7 +11136,7 @@ public class WindowManagerService extends IWindowManager.Stub } } } - if (mFinishedStarting.size() > 0) { + if (!mFinishedStarting.isEmpty()) { pw.println(); pw.println(" Finishing start of application tokens:"); for (int i=mFinishedStarting.size()-1; i>=0; i--) { @@ -11141,7 +11151,7 @@ public class WindowManagerService extends IWindowManager.Stub } } } - if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) { + if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { pw.println(); if (mOpeningApps.size() > 0) { pw.print(" mOpeningApps="); pw.println(mOpeningApps); @@ -11376,7 +11386,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition); pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation); pw.println(" mLayoutToAnim:"); - mAppTransition.dump(pw); + mAppTransition.dump(pw, " "); } } @@ -11932,5 +11942,12 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerService.this.removeWindowToken(token); } } + + @Override + public void registerAppTransitionListener(AppTransitionListener listener) { + synchronized (mWindowMap) { + mAppTransition.registerListenerLocked(listener); + } + } } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d7b537f..ad25462 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -16,21 +16,21 @@ package com.android.server.wm; +import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; +import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerService.DEBUG_POWER; import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE; import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; -import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; -import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; -import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; -import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.app.AppOpsManager; import android.os.Debug; @@ -133,7 +133,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { int mLayoutSeq = -1; - Configuration mConfiguration = null; + private Configuration mConfiguration = Configuration.EMPTY; + private Configuration mOverrideConfig = Configuration.EMPTY; // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned. // Used only on {@link #TYPE_KEYGUARD}. private boolean mConfigHasChanged; @@ -234,7 +235,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { final Rect mParentFrame = new Rect(); - // The entire screen area of the device. + // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the + // screen area of the device. final Rect mDisplayFrame = new Rect(); // The region of the display frame that the display type supports displaying content on. This @@ -344,10 +346,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { /** When true this window can be displayed on screens owther than mOwnerUid's */ private boolean mShowToOwnerOnly; - /** When true this window is at the top of the screen and should be layed out to extend under - * the status bar */ - boolean mUnderStatusBar = true; - /** * Wake lock for drawing. * Even though it's slightly more expensive to do so, we will use a separate wake lock @@ -480,6 +478,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (mAppToken != null) { final DisplayContent appDisplay = getDisplayContent(); mNotOnAppsDisplay = displayContent != appDisplay; + + if (mAppToken.showForAllUsers) { + // Windows for apps that can show for all users should also show when the + // device is locked. + mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED; + } } mWinAnimator = new WindowStateAnimator(this); @@ -518,18 +522,25 @@ final class WindowState implements WindowManagerPolicy.WindowState { public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf) { mHaveFrame = true; - TaskStack stack = mAppToken != null ? getStack() : null; - if (stack != null && !stack.isFullscreen()) { - getStackBounds(stack, mContainingFrame); - if (mUnderStatusBar) { - mContainingFrame.top = pf.top; + final TaskStack stack = mAppToken != null ? getStack() : null; + final boolean nonFullscreenStack = stack != null && !stack.isFullscreen(); + if (nonFullscreenStack) { + stack.getBounds(mContainingFrame); + final WindowState imeWin = mService.mInputMethodWindow; + if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this + && mContainingFrame.bottom > cf.bottom) { + // IME is up and obscuring this window. Adjust the window position so it is visible. + mContainingFrame.top -= mContainingFrame.bottom - cf.bottom; } + // Make sure the containing frame is within the content frame so we don't layout + // resized window under screen decorations. + mContainingFrame.intersect(cf); + mDisplayFrame.set(mContainingFrame); } else { mContainingFrame.set(pf); + mDisplayFrame.set(df); } - mDisplayFrame.set(df); - final int pw = mContainingFrame.width(); final int ph = mContainingFrame.height(); @@ -587,9 +598,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { final int fw = mFrame.width(); final int fh = mFrame.height(); - //System.out.println("In: w=" + w + " h=" + h + " container=" + - // container + " x=" + mAttrs.x + " y=" + mAttrs.y); - float x, y; if (mEnforceSizeCompat) { x = mAttrs.x * mGlobalScale; @@ -599,14 +607,19 @@ final class WindowState implements WindowManagerPolicy.WindowState { y = mAttrs.y; } + if (nonFullscreenStack) { + // Make sure window fits in containing frame since it is in a non-fullscreen stack as + // required by {@link Gravity#apply} call. + w = Math.min(w, pw); + h = Math.min(h, ph); + } + Gravity.apply(mAttrs.gravity, w, h, mContainingFrame, (int) (x + mAttrs.horizontalMargin * pw), (int) (y + mAttrs.verticalMargin * ph), mFrame); - //System.out.println("Out: " + mFrame); - - // Now make sure the window fits in the overall display. - Gravity.applyDisplay(mAttrs.gravity, df, mFrame); + // Now make sure the window fits in the overall display frame. + Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame); // Make sure the content and visible frames are inside of the // final window frame. @@ -804,14 +817,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { TaskStack getStack() { AppWindowToken wtoken = mAppToken == null ? mService.mFocusedApp : mAppToken; if (wtoken != null) { - Task task = mService.mTaskIdToTask.get(wtoken.groupId); + Task task = wtoken.mTask; if (task != null) { if (task.mStack != null) { return task.mStack; } Slog.e(TAG, "getStack: mStack null for task=" + task); } else { - Slog.e(TAG, "getStack: " + this + " couldn't find taskId=" + wtoken.groupId + Slog.e(TAG, "getStack: " + this + " couldn't find task for " + wtoken + " Callers=" + Debug.getCallers(4)); } } @@ -819,10 +832,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } void getStackBounds(Rect bounds) { - getStackBounds(getStack(), bounds); - } - - private void getStackBounds(TaskStack stack, Rect bounds) { + final TaskStack stack = getStack(); if (stack != null) { stack.getBounds(bounds); return; @@ -1070,16 +1080,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { } /** - * Return whether this window is wanting to have a translation - * animation applied to it for an in-progress move. (Only makes + * Return whether this window has moved. (Only makes * sense to call from performLayoutAndPlaceSurfacesLockedInner().) */ - boolean shouldAnimateMove() { - return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay() - && (mFrame.top != mLastFrame.top + boolean hasMoved() { + return mHasSurface && mContentChanged && !mExiting && !mWinAnimator.mLastHidden + && mService.okToDisplay() && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left) - && (mAttrs.privateFlags&PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 - && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove()); + && (mAttachedWindow == null || !mAttachedWindow.hasMoved()); } boolean isFullscreen(int screenWidth, int screenHeight) { @@ -1088,9 +1096,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { } boolean isConfigChanged() { - boolean configChanged = mConfiguration != mService.mCurConfiguration - && (mConfiguration == null - || (mConfiguration.diff(mService.mCurConfiguration) != 0)); + final TaskStack stack = getStack(); + final Configuration overrideConfig = + (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY; + final Configuration serviceConfig = mService.mCurConfiguration; + boolean configChanged = + (mConfiguration != serviceConfig && mConfiguration.diff(serviceConfig) != 0) + || (mOverrideConfig != overrideConfig && !mOverrideConfig.equals(overrideConfig)); if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { // Retain configuration changed status until resetConfiguration called. @@ -1119,8 +1131,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } - void setConfiguration(final Configuration newConfig) { + private void setConfiguration( + final Configuration newConfig, final Configuration newOverrideConfig) { mConfiguration = newConfig; + mOverrideConfig = newOverrideConfig; mConfigHasChanged = false; } @@ -1152,10 +1166,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { WindowState win = mService.windowForClientLocked(mSession, mClient, false); Slog.i(TAG, "WIN DEATH: " + win); if (win != null) { - mService.removeWindowLocked(mSession, win); + mService.removeWindowLocked(win); } else if (mHasSurface) { Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid."); - mService.removeWindowLocked(mSession, WindowState.this); + mService.removeWindowLocked(WindowState.this); } } } catch (IllegalArgumentException ex) { @@ -1328,6 +1342,15 @@ final class WindowState implements WindowManagerPolicy.WindowState { return displayContent.isDefaultDisplay; } + @Override + public boolean isDimming() { + TaskStack stack = getStack(); + if (stack == null) { + return false; + } + return stack.isDimming(mWinAnimator); + } + public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { mShowToOwnerOnly = showToOwnerOnly; } @@ -1339,7 +1362,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { win = win.mAttachedWindow; } if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW - && win.mAppToken != null && win.mAppToken.showWhenLocked) { + && win.mAppToken != null && win.mAppToken.showForAllUsers) { // Save some cycles by not calling getDisplayInfo unless it is an application // window intended for all users. final DisplayContent displayContent = win.getDisplayContent(); @@ -1423,12 +1446,15 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this + ": " + mCompatFrame); boolean configChanged = isConfigChanged(); + final TaskStack stack = getStack(); + final Configuration overrideConfig = + (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY; if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) { Slog.i(TAG, "Sending new config to window " + this + ": " - + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH - + " / " + mService.mCurConfiguration); + + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH + " / config=" + + mService.mCurConfiguration + " overrideConfig=" + overrideConfig); } - setConfiguration(mService.mCurConfiguration); + setConfiguration(mService.mCurConfiguration, overrideConfig); if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); @@ -1505,7 +1531,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { } void dump(PrintWriter pw, String prefix, boolean dumpAll) { + final TaskStack stack = getStack(); pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId()); + if (stack != null) { + pw.print(" stackId="); pw.print(stack.mStackId); + } pw.print(" mSession="); pw.print(mSession); pw.print(" mClient="); pw.println(mClient.asBinder()); pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid); @@ -1589,6 +1619,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(prefix); pw.print("touchable region="); pw.println(region); } pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration); + if (mOverrideConfig != Configuration.EMPTY) { + pw.print(prefix); pw.print("mOverrideConfig="); pw.println(mOverrideConfig); + } } pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); pw.print(" mShownFrame="); mShownFrame.printShortString(pw); @@ -1599,6 +1632,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.println(); pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw); pw.print(" last="); mLastSystemDecorRect.printShortString(pw); + if (mWinAnimator.mHasClipRect) { + pw.print(" mLastClipRect="); + mWinAnimator.mLastClipRect.printShortString(pw); + } pw.println(); } if (mEnforceSizeCompat) { @@ -1669,7 +1706,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.println(mWallpaperDisplayOffsetY); } if (mDrawLock != null) { - pw.println("mDrawLock=" + mDrawLock); + pw.print(prefix); pw.println("mDrawLock=" + mDrawLock); } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 4cdfc41..d6726c1 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -53,21 +53,16 @@ import android.view.View; import android.view.WindowManager; import android.view.WindowManagerPolicy; import android.view.WindowManager.LayoutParams; -import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; -import com.android.internal.R; import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; import java.util.ArrayList; -class WinAnimatorList extends ArrayList<WindowStateAnimator> { -} - /** * Keep track of animations and surface operations for a single WindowState. **/ @@ -85,10 +80,6 @@ class WindowStateAnimator { final Context mContext; final boolean mIsWallpaper; - // If this is a universe background window, this is the transformation - // it is applying to the rest of the universe. - final Transformation mUniverseTransform = new Transformation(); - // Currently running animation. boolean mAnimating; boolean mLocalAnimating; @@ -189,7 +180,7 @@ class WindowStateAnimator { int mAttrType; - public WindowStateAnimator(final WindowState win) { + WindowStateAnimator(final WindowState win) { final WindowManagerService service = win.mService; mService = service; @@ -247,9 +238,7 @@ class WindowStateAnimator { boolean isAnimating() { return mAnimation != null || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null) - || (mAppAnimator != null && - (mAppAnimator.animation != null - || mAppAnimator.mAppToken.inPendingTransaction)); + || (mAppAnimator != null && mAppAnimator.isAnimating()); } /** Is the window animating the DummyAnimation? */ @@ -486,7 +475,7 @@ class WindowStateAnimator { mService.mPendingRemove.add(mWin); mWin.mRemoveOnExit = false; } - mAnimator.hideWallpapersLocked(mWin); + mService.hideWallpapersLocked(mWin); } void hide() { @@ -527,7 +516,7 @@ class WindowStateAnimator { } // This must be called while inside a transaction. - boolean commitFinishDrawingLocked(long currentTime) { + boolean commitFinishDrawingLocked() { if (DEBUG_STARTING_WINDOW && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState=" @@ -984,7 +973,7 @@ class WindowStateAnimator { } mSurfaceControl.destroy(); } - mAnimator.hideWallpapersLocked(mWin); + mService.hideWallpapersLocked(mWin); } catch (RuntimeException e) { Slog.w(TAG, "Exception thrown when destroying Window " + this + " surface " + mSurfaceControl + " session " + mSession @@ -1010,7 +999,7 @@ class WindowStateAnimator { WindowManagerService.logSurface(mWin, "DESTROY PENDING", e); } mPendingDestroySurface.destroy(); - mAnimator.hideWallpapersLocked(mWin); + mService.hideWallpapersLocked(mWin); } } catch (RuntimeException e) { Slog.w(TAG, "Exception thrown when destroying Window " @@ -1096,9 +1085,6 @@ class WindowStateAnimator { if (appTransformation != null) { tmpMatrix.postConcat(appTransformation.getMatrix()); } - if (mAnimator.mUniverseBackground != null) { - tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); - } if (screenAnimation) { tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix()); } @@ -1164,9 +1150,6 @@ class WindowStateAnimator { mHasClipRect = true; } } - if (mAnimator.mUniverseBackground != null) { - mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); - } if (screenAnimation) { mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha(); } @@ -1192,15 +1175,12 @@ class WindowStateAnimator { TAG, "computeShownFrameLocked: " + this + " not attached, mAlpha=" + mAlpha); - final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null - && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND - && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer); MagnificationSpec spec = null; //TODO (multidisplay): Magnification is supported only for the default display. if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) { spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin); } - if (applyUniverseTransformation || spec != null) { + if (spec != null) { final Rect frame = mWin.mFrame; final float tmpFloats[] = mService.mTmpFloats; final Matrix tmpMatrix = mWin.mTmpMatrix; @@ -1208,10 +1188,6 @@ class WindowStateAnimator { tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale); tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); - if (applyUniverseTransformation) { - tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix()); - } - if (spec != null && !spec.isNop()) { tmpMatrix.postScale(spec.scale, spec.scale); tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); @@ -1231,9 +1207,6 @@ class WindowStateAnimator { mWin.mShownFrame.set(x, y, x + w, y + h); mShownAlpha = mAlpha; - if (applyUniverseTransformation) { - mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha(); - } } else { mWin.mShownFrame.set(mWin.mFrame); if (mWin.mXOffset != 0 || mWin.mYOffset != 0) { @@ -1248,7 +1221,7 @@ class WindowStateAnimator { } } - void applyDecorRect(final Rect decorRect) { + private void applyDecorRect(final Rect decorRect) { final WindowState w = mWin; final int width = w.mFrame.width(); final int height = w.mFrame.height(); @@ -1301,17 +1274,9 @@ class WindowStateAnimator { displayInfo.logicalHeight - w.mCompatFrame.top); } else if (w.mLayer >= mService.mSystemDecorLayer) { // Above the decor layer is easy, just use the entire window. - // Unless we have a universe background... in which case all the - // windows need to be cropped by the screen, so they don't cover - // the universe background. - if (mAnimator.mUniverseBackground == null) { - w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); - } else { - applyDecorRect(mService.mScreenRect); - } - } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND - || w.mDecorFrame.isEmpty()) { - // The universe background isn't cropped, nor windows without policy decor. + w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); + } else if (w.mDecorFrame.isEmpty()) { + // Windows without policy decor aren't cropped. w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height()); } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) { // If we're animating, the wallpaper crop should only be updated at the end of the @@ -1436,6 +1401,9 @@ class WindowStateAnimator { if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, "SIZE " + width + "x" + height, null); mSurfaceControl.setSize(width, height); + mSurfaceControl.setMatrix( + mDsDx * w.mHScale, mDtDx * w.mVScale, + mDsDy * w.mHScale, mDtDy * w.mVScale); mAnimator.setPendingLayoutChanges(w.getDisplayId(), WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { @@ -1482,7 +1450,7 @@ class WindowStateAnimator { hide(); } else if (w.mAttachedHidden || !w.isOnScreen()) { hide(); - mAnimator.hideWallpapersLocked(w); + mService.hideWallpapersLocked(w); // If we are waiting for this window to handle an // orientation change, well, it is hidden, so @@ -1654,13 +1622,8 @@ class WindowStateAnimator { } if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) { - RuntimeException e = null; - if (!WindowManagerService.HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); - } Slog.v(TAG, "performShow on " + this - + ": mDrawState=" + mDrawState + " readyForDisplay=" + + ": mDrawState=" + drawStateToString() + " readyForDisplay=" + mWin.isReadyForDisplayIgnoringKeyguard() + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING) + " during animation: policyVis=" + mWin.mPolicyVisibility @@ -1671,7 +1634,8 @@ class WindowStateAnimator { + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false) + " animating=" + mAnimating + " tok animating=" - + (mAppAnimator != null ? mAppAnimator.animating : false), e); + + (mAppAnimator != null ? mAppAnimator.animating : false) + " Callers=" + + Debug.getCallers(3)); } if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) { if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) @@ -1932,11 +1896,6 @@ class WindowStateAnimator { pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); } - if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) { - pw.print(prefix); pw.print("mUniverseTransform="); - mUniverseTransform.printShortString(pw); - pw.println(); - } if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) { pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha); pw.print(" mAlpha="); pw.print(mAlpha); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 1a672e6..b303505 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -83,8 +83,9 @@ class WindowToken { WindowState win = windows.get(winNdx); if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win); - win.mService.removeWindowLocked(win.mSession, win); + win.mService.removeWindowLocked(win); } + windows.clear(); } void dump(PrintWriter pw, String prefix) { |