Explode WindowManagerService.
Change-Id: I3d73ed4c9a1b5d730aeffeb2df24ce5e6117d698
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
new file mode 100644
index 0000000..d3d9df4
--- /dev/null
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.pm.ActivityInfo;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.IApplicationToken;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Version of WindowToken that is specifically for a particular application (or
+ * really activity) that is displaying windows.
+ */
+class AppWindowToken extends WindowToken {
+ // Non-null only for application tokens.
+ final IApplicationToken appToken;
+
+ // All of the windows and child windows that are included in this
+ // application token. Note this list is NOT sorted!
+ final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
+
+ int groupId = -1;
+ boolean appFullscreen;
+ int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+ // The input dispatching timeout for this application token in nanoseconds.
+ long inputDispatchingTimeoutNanos;
+
+ // These are used for determining when all windows associated with
+ // an activity have been drawn, so they can be made visible together
+ // at the same time.
+ int lastTransactionSequence;
+ int numInterestingWindows;
+ int numDrawnWindows;
+ boolean inPendingTransaction;
+ boolean allDrawn;
+
+ // Is this token going to be hidden in a little while? If so, it
+ // won't be taken into account for setting the screen orientation.
+ boolean willBeHidden;
+
+ // Is this window's surface needed? This is almost like hidden, except
+ // it will sometimes be true a little earlier: when the token has
+ // been shown, but is still waiting for its app transition to execute
+ // before making its windows shown.
+ boolean hiddenRequested;
+
+ // Have we told the window clients to hide themselves?
+ boolean clientHidden;
+
+ // Last visibility state we reported to the app token.
+ boolean reportedVisible;
+
+ // Set to true when the token has been removed from the window mgr.
+ boolean removed;
+
+ // Have we been asked to have this token keep the screen frozen?
+ boolean freezingScreen;
+
+ boolean animating;
+ Animation animation;
+ boolean hasTransformation;
+ final Transformation transformation = new Transformation();
+
+ // Offset to the window of all layers in the token, for use by
+ // AppWindowToken animations.
+ int animLayerAdjustment;
+
+ // Information about an application starting window if displayed.
+ StartingData startingData;
+ WindowState startingWindow;
+ View startingView;
+ boolean startingDisplayed;
+ boolean startingMoved;
+ boolean firstWindowDrawn;
+
+ // Input application handle used by the input dispatcher.
+ InputApplicationHandle mInputApplicationHandle;
+
+ AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
+ super(_service, _token.asBinder(),
+ WindowManager.LayoutParams.TYPE_APPLICATION, true);
+ appWindowToken = this;
+ appToken = _token;
+ mInputApplicationHandle = new InputApplicationHandle(this);
+ lastTransactionSequence = service.mTransactionSequence-1;
+ }
+
+ public void setAnimation(Animation anim) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+ animation = anim;
+ animating = false;
+ anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+ anim.scaleCurrentDuration(service.mTransitionAnimationScale);
+ int zorder = anim.getZAdjustment();
+ int adj = 0;
+ if (zorder == Animation.ZORDER_TOP) {
+ adj = WindowManagerService.TYPE_LAYER_OFFSET;
+ } else if (zorder == Animation.ZORDER_BOTTOM) {
+ adj = -WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+
+ if (animLayerAdjustment != adj) {
+ animLayerAdjustment = adj;
+ updateLayers();
+ }
+ }
+
+ public void setDummyAnimation() {
+ if (animation == null) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Setting dummy animation in " + this);
+ animation = WindowManagerService.sDummyAnimation;
+ }
+ }
+
+ public void clearAnimation() {
+ if (animation != null) {
+ animation = null;
+ animating = true;
+ }
+ }
+
+ void updateLayers() {
+ final int N = allAppWindows.size();
+ final int adj = animLayerAdjustment;
+ for (int i=0; i<N; i++) {
+ WindowState w = allAppWindows.get(i);
+ w.mAnimLayer = w.mLayer + adj;
+ if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
+ + w.mAnimLayer);
+ if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
+ service.setInputMethodAnimLayerAdjustment(adj);
+ }
+ if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
+ service.setWallpaperAnimLayerAdjustmentLocked(adj);
+ }
+ }
+ }
+
+ void sendAppVisibilityToClients() {
+ final int N = allAppWindows.size();
+ for (int i=0; i<N; i++) {
+ WindowState win = allAppWindows.get(i);
+ if (win == startingWindow && clientHidden) {
+ // Don't hide the starting window.
+ continue;
+ }
+ try {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+ "Setting visibility of " + win + ": " + (!clientHidden));
+ win.mClient.dispatchAppVisibility(!clientHidden);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ void showAllWindowsLocked() {
+ final int NW = allAppWindows.size();
+ for (int i=0; i<NW; i++) {
+ WindowState w = allAppWindows.get(i);
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+ "performing show on: " + w);
+ w.performShowLocked();
+ }
+ }
+
+ // This must be called while inside a transaction.
+ boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+ if (!service.mDisplayFrozen && service.mPolicy.isScreenOn()) {
+ // We will run animations as long as the display isn't frozen.
+
+ if (animation == WindowManagerService.sDummyAnimation) {
+ // This guy is going to animate, but not yet. For now count
+ // it as not animating for purposes of scheduling transactions;
+ // when it is really time to animate, this will be set to
+ // a real animation and the next call will execute normally.
+ return false;
+ }
+
+ if ((allDrawn || animating || startingDisplayed) && animation != null) {
+ if (!animating) {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Starting animation in " + this +
+ " @ " + currentTime + ": dw=" + dw + " dh=" + dh
+ + " scale=" + service.mTransitionAnimationScale
+ + " allDrawn=" + allDrawn + " animating=" + animating);
+ animation.initialize(dw, dh, dw, dh);
+ animation.setStartTime(currentTime);
+ animating = true;
+ }
+ transformation.clear();
+ final boolean more = animation.getTransformation(
+ currentTime, transformation);
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Stepped animation in " + this +
+ ": more=" + more + ", xform=" + transformation);
+ if (more) {
+ // we're done!
+ hasTransformation = true;
+ return true;
+ }
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Finished animation in " + this +
+ " @ " + currentTime);
+ animation = null;
+ }
+ } else if (animation != null) {
+ // If the display is frozen, and there is a pending animation,
+ // clear it and make sure we run the cleanup code.
+ animating = true;
+ animation = null;
+ }
+
+ hasTransformation = false;
+
+ if (!animating) {
+ return false;
+ }
+
+ clearAnimation();
+ animating = false;
+ if (animLayerAdjustment != 0) {
+ animLayerAdjustment = 0;
+ updateLayers();
+ }
+ if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
+ service.moveInputMethodWindowsIfNeededLocked(true);
+ }
+
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Animation done in " + this
+ + ": reportedVisible=" + reportedVisible);
+
+ transformation.clear();
+
+ final int N = windows.size();
+ for (int i=0; i<N; i++) {
+ windows.get(i).finishExit();
+ }
+ updateReportedVisibilityLocked();
+
+ return false;
+ }
+
+ void updateReportedVisibilityLocked() {
+ if (appToken == null) {
+ return;
+ }
+
+ int numInteresting = 0;
+ int numVisible = 0;
+ boolean nowGone = true;
+
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
+ final int N = allAppWindows.size();
+ for (int i=0; i<N; i++) {
+ WindowState win = allAppWindows.get(i);
+ if (win == startingWindow || win.mAppFreezing
+ || win.mViewVisibility != View.VISIBLE
+ || win.mAttrs.type == TYPE_APPLICATION_STARTING
+ || win.mDestroying) {
+ continue;
+ }
+ if (WindowManagerService.DEBUG_VISIBILITY) {
+ Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
+ + win.isDrawnLw()
+ + ", isAnimating=" + win.isAnimating());
+ if (!win.isDrawnLw()) {
+ Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
+ + " pv=" + win.mPolicyVisibility
+ + " dp=" + win.mDrawPending
+ + " cdp=" + win.mCommitDrawPending
+ + " ah=" + win.mAttachedHidden
+ + " th="
+ + (win.mAppToken != null
+ ? win.mAppToken.hiddenRequested : false)
+ + " a=" + win.mAnimating);
+ }
+ }
+ numInteresting++;
+ if (win.isDrawnLw()) {
+ if (!win.isAnimating()) {
+ numVisible++;
+ }
+ nowGone = false;
+ } else if (win.isAnimating()) {
+ nowGone = false;
+ }
+ }
+
+ boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
+ + numInteresting + " visible=" + numVisible);
+ if (nowVisible != reportedVisible) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
+ WindowManagerService.TAG, "Visibility changed in " + this
+ + ": vis=" + nowVisible);
+ reportedVisible = nowVisible;
+ Message m = service.mH.obtainMessage(
+ H.REPORT_APPLICATION_TOKEN_WINDOWS,
+ nowVisible ? 1 : 0,
+ nowGone ? 1 : 0,
+ this);
+ service.mH.sendMessage(m);
+ }
+ }
+
+ WindowState findMainWindow() {
+ int j = windows.size();
+ while (j > 0) {
+ j--;
+ WindowState win = windows.get(j);
+ if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
+ || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+ return win;
+ }
+ }
+ return null;
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ super.dump(pw, prefix);
+ if (appToken != null) {
+ pw.print(prefix); pw.println("app=true");
+ }
+ 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(" requestedOrientation="); pw.println(requestedOrientation);
+ pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
+ pw.print(" clientHidden="); pw.print(clientHidden);
+ pw.print(" willBeHidden="); pw.print(willBeHidden);
+ pw.print(" reportedVisible="); pw.println(reportedVisible);
+ if (paused || freezingScreen) {
+ pw.print(prefix); pw.print("paused="); pw.print(paused);
+ pw.print(" freezingScreen="); pw.println(freezingScreen);
+ }
+ if (numInterestingWindows != 0 || numDrawnWindows != 0
+ || inPendingTransaction || allDrawn) {
+ pw.print(prefix); pw.print("numInterestingWindows=");
+ pw.print(numInterestingWindows);
+ pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
+ pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
+ pw.print(" allDrawn="); pw.println(allDrawn);
+ }
+ if (animating || animation != null) {
+ pw.print(prefix); pw.print("animating="); pw.print(animating);
+ pw.print(" animation="); pw.println(animation);
+ }
+ if (hasTransformation) {
+ pw.print(prefix); pw.print("XForm: ");
+ transformation.printShortString(pw);
+ pw.println();
+ }
+ if (animLayerAdjustment != 0) {
+ pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+ }
+ if (startingData != null || removed || firstWindowDrawn) {
+ pw.print(prefix); pw.print("startingData="); pw.print(startingData);
+ pw.print(" removed="); pw.print(removed);
+ pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
+ }
+ if (startingWindow != null || startingView != null
+ || startingDisplayed || startingMoved) {
+ pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
+ pw.print(" startingView="); pw.print(startingView);
+ pw.print(" startingDisplayed="); pw.print(startingDisplayed);
+ pw.print(" startingMoved"); pw.println(startingMoved);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (stringName == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("AppWindowToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" token="); sb.append(token); sb.append('}');
+ stringName = sb.toString();
+ }
+ return stringName;
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
new file mode 100644
index 0000000..1fcb869
--- /dev/null
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+import java.io.PrintWriter;
+
+/**
+ * DimAnimator class that controls the dim animation. This holds the surface and
+ * all state used for dim animation.
+ */
+class DimAnimator {
+ Surface mDimSurface;
+ boolean mDimShown = false;
+ float mDimCurrentAlpha;
+ float mDimTargetAlpha;
+ float mDimDeltaPerMs;
+ long mLastDimAnimTime;
+
+ int mLastDimWidth, mLastDimHeight;
+
+ DimAnimator (SurfaceSession session) {
+ if (mDimSurface == null) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ + mDimSurface + ": CREATE");
+ try {
+ mDimSurface = new Surface(session, 0,
+ "DimSurface",
+ -1, 16, 16, PixelFormat.OPAQUE,
+ Surface.FX_SURFACE_DIM);
+ mDimSurface.setAlpha(0.0f);
+ } catch (Exception e) {
+ Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
+ }
+ }
+ }
+
+ /**
+ * Show the dim surface.
+ */
+ void show(int dw, int dh) {
+ if (!mDimShown) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
+ dw + "x" + dh + ")");
+ mDimShown = true;
+ try {
+ mLastDimWidth = dw;
+ mLastDimHeight = dh;
+ mDimSurface.setPosition(0, 0);
+ mDimSurface.setSize(dw, dh);
+ mDimSurface.show();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Failure showing dim surface", e);
+ }
+ } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
+ mLastDimWidth = dw;
+ mLastDimHeight = dh;
+ mDimSurface.setSize(dw, dh);
+ }
+ }
+
+ /**
+ * Set's the dim surface's layer and update dim parameters that will be used in
+ * {@link updateSurface} after all windows are examined.
+ */
+ void updateParameters(Resources res, WindowState w, long currentTime) {
+ mDimSurface.setLayer(w.mAnimLayer-1);
+
+ final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface
+ + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
+ if (mDimTargetAlpha != target) {
+ // If the desired dim level has changed, then
+ // start an animation to it.
+ mLastDimAnimTime = currentTime;
+ long duration = (w.mAnimating && w.mAnimation != null)
+ ? w.mAnimation.computeDurationHint()
+ : WindowManagerService.DEFAULT_DIM_DURATION;
+ if (target > mDimTargetAlpha) {
+ TypedValue tv = new TypedValue();
+ res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
+ tv, true);
+ if (tv.type == TypedValue.TYPE_FRACTION) {
+ duration = (long)tv.getFraction((float)duration, (float)duration);
+ } else if (tv.type >= TypedValue.TYPE_FIRST_INT
+ && tv.type <= TypedValue.TYPE_LAST_INT) {
+ duration = tv.data;
+ }
+ }
+ if (duration < 1) {
+ // Don't divide by zero
+ duration = 1;
+ }
+ mDimTargetAlpha = target;
+ mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
+ }
+ }
+
+ /**
+ * Updating the surface's alpha. Returns true if the animation continues, or returns
+ * false when the animation is finished and the dim surface is hidden.
+ */
+ boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
+ if (!dimming) {
+ if (mDimTargetAlpha != 0) {
+ mLastDimAnimTime = currentTime;
+ mDimTargetAlpha = 0;
+ mDimDeltaPerMs = (-mDimCurrentAlpha) / WindowManagerService.DEFAULT_DIM_DURATION;
+ }
+ }
+
+ boolean animating = false;
+ if (mLastDimAnimTime != 0) {
+ mDimCurrentAlpha += mDimDeltaPerMs
+ * (currentTime-mLastDimAnimTime);
+ boolean more = true;
+ if (displayFrozen) {
+ // If the display is frozen, there is no reason to animate.
+ more = false;
+ } else if (mDimDeltaPerMs > 0) {
+ if (mDimCurrentAlpha > mDimTargetAlpha) {
+ more = false;
+ }
+ } else if (mDimDeltaPerMs < 0) {
+ if (mDimCurrentAlpha < mDimTargetAlpha) {
+ more = false;
+ }
+ } else {
+ more = false;
+ }
+
+ // Do we need to continue animating?
+ if (more) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ + mDimSurface + ": alpha=" + mDimCurrentAlpha);
+ mLastDimAnimTime = currentTime;
+ mDimSurface.setAlpha(mDimCurrentAlpha);
+ animating = true;
+ } else {
+ mDimCurrentAlpha = mDimTargetAlpha;
+ mLastDimAnimTime = 0;
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM "
+ + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
+ mDimSurface.setAlpha(mDimCurrentAlpha);
+ if (!dimming) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface
+ + ": HIDE");
+ try {
+ mDimSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Illegal argument exception hiding dim surface");
+ }
+ mDimShown = false;
+ }
+ }
+ }
+ return animating;
+ }
+
+ public void printTo(PrintWriter pw) {
+ pw.print(" mDimShown="); pw.print(mDimShown);
+ pw.print(" current="); pw.print(mDimCurrentAlpha);
+ pw.print(" target="); pw.print(mDimTargetAlpha);
+ pw.print(" delta="); pw.print(mDimDeltaPerMs);
+ pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
new file mode 100644
index 0000000..c8f8ff3
--- /dev/null
+++ b/services/java/com/android/server/wm/DragState.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.DragEvent;
+import android.view.InputChannel;
+import android.view.InputQueue;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import java.util.ArrayList;
+
+/**
+ * Drag/drop state
+ */
+class DragState {
+ final WindowManagerService mService;
+ IBinder mToken;
+ Surface mSurface;
+ int mFlags;
+ IBinder mLocalWin;
+ ClipData mData;
+ ClipDescription mDataDescription;
+ boolean mDragResult;
+ float mCurrentX, mCurrentY;
+ float mThumbOffsetX, mThumbOffsetY;
+ InputChannel mServerChannel, mClientChannel;
+ WindowState mTargetWindow;
+ ArrayList<WindowState> mNotifiedWindows;
+ boolean mDragInProgress;
+
+ private final Region mTmpRegion = new Region();
+
+ DragState(WindowManagerService service, IBinder token, Surface surface,
+ int flags, IBinder localWin) {
+ mService = service;
+ mToken = token;
+ mSurface = surface;
+ mFlags = flags;
+ mLocalWin = localWin;
+ mNotifiedWindows = new ArrayList<WindowState>();
+ }
+
+ void reset() {
+ if (mSurface != null) {
+ mSurface.destroy();
+ }
+ mSurface = null;
+ mFlags = 0;
+ mLocalWin = null;
+ mToken = null;
+ mData = null;
+ mThumbOffsetX = mThumbOffsetY = 0;
+ mNotifiedWindows = null;
+ }
+
+ void register() {
+ if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "registering drag input channel");
+ if (mClientChannel != null) {
+ Slog.e(WindowManagerService.TAG, "Duplicate register of drag input channel");
+ } else {
+ InputChannel[] channels = InputChannel.openInputChannelPair("drag");
+ mServerChannel = channels[0];
+ mClientChannel = channels[1];
+ mService.mInputManager.registerInputChannel(mServerChannel, null);
+ InputQueue.registerInputChannel(mClientChannel, mService.mDragInputHandler,
+ mService.mH.getLooper().getQueue());
+ }
+ }
+
+ void unregister() {
+ if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "unregistering drag input channel");
+ if (mClientChannel == null) {
+ Slog.e(WindowManagerService.TAG, "Unregister of nonexistent drag input channel");
+ } else {
+ mService.mInputManager.unregisterInputChannel(mServerChannel);
+ InputQueue.unregisterInputChannel(mClientChannel);
+ mClientChannel.dispose();
+ mServerChannel.dispose();
+ mClientChannel = null;
+ mServerChannel = null;
+ }
+ }
+
+ int getDragLayerLw() {
+ return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+
+ /* call out to each visible window/session informing it about the drag
+ */
+ void broadcastDragStartedLw(final float touchX, final float touchY) {
+ // Cache a base-class instance of the clip metadata so that parceling
+ // works correctly in calling out to the apps.
+ mDataDescription = (mData != null) ? mData.getDescription() : null;
+ mNotifiedWindows.clear();
+ mDragInProgress = true;
+
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
+ }
+
+ final int N = mService.mWindows.size();
+ for (int i = 0; i < N; i++) {
+ sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
+ }
+ }
+
+ /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
+ * designated window is potentially a drop recipient. There are race situations
+ * around DRAG_ENDED broadcast, so we make sure that once we've declared that
+ * the drag has ended, we never send out another DRAG_STARTED for this drag action.
+ *
+ * This method clones the 'event' parameter if it's being delivered to the same
+ * process, so it's safe for the caller to call recycle() on the event afterwards.
+ */
+ private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
+ ClipDescription desc) {
+ // Don't actually send the event if the drag is supposed to be pinned
+ // to the originating window but 'newWin' is not that window.
+ if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
+ final IBinder winBinder = newWin.mClient.asBinder();
+ if (winBinder != mLocalWin) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "Not dispatching local DRAG_STARTED to " + newWin);
+ }
+ return;
+ }
+ }
+
+ if (mDragInProgress && newWin.isPotentialDragTarget()) {
+ DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
+ touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
+ null, desc, null, false);
+ try {
+ newWin.mClient.dispatchDragEvent(event);
+ // track each window that we've notified that the drag is starting
+ mNotifiedWindows.add(newWin);
+ } catch (RemoteException e) {
+ Slog.w(WindowManagerService.TAG, "Unable to drag-start window " + newWin);
+ } finally {
+ // if the callee was local, the dispatch has already recycled the event
+ if (Process.myPid() != newWin.mSession.mPid) {
+ event.recycle();
+ }
+ }
+ }
+ }
+
+ /* helper - construct and send a DRAG_STARTED event only if the window has not
+ * previously been notified, i.e. it became visible after the drag operation
+ * was begun. This is a rare case.
+ */
+ void sendDragStartedIfNeededLw(WindowState newWin) {
+ if (mDragInProgress) {
+ // If we have sent the drag-started, we needn't do so again
+ for (WindowState ws : mNotifiedWindows) {
+ if (ws == newWin) {
+ return;
+ }
+ }
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "need to send DRAG_STARTED to new window " + newWin);
+ }
+ sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
+ }
+ }
+
+ void broadcastDragEndedLw() {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "broadcasting DRAG_ENDED");
+ }
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
+ 0, 0, null, null, null, mDragResult);
+ for (WindowState ws: mNotifiedWindows) {
+ try {
+ ws.mClient.dispatchDragEvent(evt);
+ } catch (RemoteException e) {
+ Slog.w(WindowManagerService.TAG, "Unable to drag-end window " + ws);
+ }
+ }
+ mNotifiedWindows.clear();
+ mDragInProgress = false;
+ evt.recycle();
+ }
+
+ void endDragLw() {
+ mService.mDragState.broadcastDragEndedLw();
+
+ // stop intercepting input
+ mService.mDragState.unregister();
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ // free our resources and drop all the object references
+ mService.mDragState.reset();
+ mService.mDragState = null;
+
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation");
+ boolean changed = mService.setRotationUncheckedLocked(
+ WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
+ if (changed) {
+ mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ }
+ }
+
+ void notifyMoveLw(float x, float y) {
+ final int myPid = Process.myPid();
+
+ // Move the surface to the given touch
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
+ Surface.openTransaction();
+ try {
+ mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DRAG "
+ + mSurface + ": pos=(" +
+ (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
+ }
+
+ // Tell the affected window
+ WindowState touchedWin = getTouchedWinAtPointLw(x, y);
+ if (touchedWin == null) {
+ if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "No touched win at x=" + x + " y=" + y);
+ return;
+ }
+ if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
+ final IBinder touchedBinder = touchedWin.mClient.asBinder();
+ if (touchedBinder != mLocalWin) {
+ // This drag is pinned only to the originating window, but the drag
+ // point is outside that window. Pretend it's over empty space.
+ touchedWin = null;
+ }
+ }
+ try {
+ // have we dragged over a new window?
+ if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "sending DRAG_EXITED to " + mTargetWindow);
+ }
+ // force DRAG_EXITED_EVENT if appropriate
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
+ x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
+ null, null, null, false);
+ mTargetWindow.mClient.dispatchDragEvent(evt);
+ if (myPid != mTargetWindow.mSession.mPid) {
+ evt.recycle();
+ }
+ }
+ if (touchedWin != null) {
+ if (false && WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "sending DRAG_LOCATION to " + touchedWin);
+ }
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
+ x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+ null, null, null, false);
+ touchedWin.mClient.dispatchDragEvent(evt);
+ if (myPid != touchedWin.mSession.mPid) {
+ evt.recycle();
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.w(WindowManagerService.TAG, "can't send drag notification to windows");
+ }
+ mTargetWindow = touchedWin;
+ }
+
+ // Tell the drop target about the data. Returns 'true' if we can immediately
+ // dispatch the global drag-ended message, 'false' if we need to wait for a
+ // result from the recipient.
+ boolean notifyDropLw(float x, float y) {
+ WindowState touchedWin = getTouchedWinAtPointLw(x, y);
+ if (touchedWin == null) {
+ // "drop" outside a valid window -- no recipient to apply a
+ // timeout to, and we can send the drag-ended message immediately.
+ mDragResult = false;
+ return true;
+ }
+
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "sending DROP to " + touchedWin);
+ }
+ final int myPid = Process.myPid();
+ final IBinder token = touchedWin.mClient.asBinder();
+ DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
+ x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
+ null, null, mData, false);
+ try {
+ touchedWin.mClient.dispatchDragEvent(evt);
+
+ // 5 second timeout for this window to respond to the drop
+ mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
+ Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
+ mService.mH.sendMessageDelayed(msg, 5000);
+ } catch (RemoteException e) {
+ Slog.w(WindowManagerService.TAG, "can't send drop notification to win " + touchedWin);
+ return true;
+ } finally {
+ if (myPid != touchedWin.mSession.mPid) {
+ evt.recycle();
+ }
+ }
+ mToken = token;
+ return false;
+ }
+
+ // Find the visible, touch-deliverable window under the given point
+ private WindowState getTouchedWinAtPointLw(float xf, float yf) {
+ WindowState touchedWin = null;
+ final int x = (int) xf;
+ final int y = (int) yf;
+ final ArrayList<WindowState> windows = mService.mWindows;
+ final int N = windows.size();
+ for (int i = N - 1; i >= 0; i--) {
+ WindowState child = windows.get(i);
+ final int flags = child.mAttrs.flags;
+ if (!child.isVisibleLw()) {
+ // not visible == don't tell about drags
+ continue;
+ }
+ if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
+ // not touchable == don't tell about drags
+ continue;
+ }
+
+ child.getTouchableRegion(mTmpRegion);
+
+ final int touchFlags = flags &
+ (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
+ if (mTmpRegion.contains(x, y) || touchFlags == 0) {
+ // Found it
+ touchedWin = child;
+ break;
+ }
+ }
+
+ return touchedWin;
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/FadeInOutAnimation.java b/services/java/com/android/server/wm/FadeInOutAnimation.java
new file mode 100644
index 0000000..06f7657
--- /dev/null
+++ b/services/java/com/android/server/wm/FadeInOutAnimation.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+/**
+ * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
+ * This is used for opening/closing transition for apps in compatible mode.
+ */
+class FadeInOutAnimation extends Animation {
+ boolean mFadeIn;
+
+ public FadeInOutAnimation(boolean fadeIn) {
+ setInterpolator(new AccelerateInterpolator());
+ setDuration(WindowManagerService.DEFAULT_FADE_IN_OUT_DURATION);
+ mFadeIn = fadeIn;
+ }
+
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ float x = interpolatedTime;
+ if (!mFadeIn) {
+ x = 1.0f - x; // reverse the interpolation for fade out
+ }
+ t.setAlpha(x);
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/wm/InputApplicationHandle.java
index c95e525..64c8e7e 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/wm/InputApplicationHandle.java
@@ -30,11 +30,11 @@
private int ptr;
// The window manager's application window token.
- public final WindowManagerService.AppWindowToken appWindowToken;
+ public final AppWindowToken appWindowToken;
private native void nativeDispose();
- public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+ public InputApplicationHandle(AppWindowToken appWindowToken) {
this.appWindowToken = appWindowToken;
}
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
new file mode 100644
index 0000000..34f3618
--- /dev/null
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -0,0 +1,364 @@
+/**
+ *
+ */
+package com.android.server.wm;
+
+import android.graphics.Rect;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import java.util.ArrayList;
+
+final class InputMonitor {
+ private final WindowManagerService mService;
+
+ // Current window with input focus for keys and other non-touch events. May be null.
+ private WindowState mInputFocus;
+
+ // When true, prevents input dispatch from proceeding until set to false again.
+ private boolean mInputDispatchFrozen;
+
+ // When true, input dispatch proceeds normally. Otherwise all events are dropped.
+ private boolean mInputDispatchEnabled = true;
+
+ // When true, need to call updateInputWindowsLw().
+ private boolean mUpdateInputWindowsNeeded = true;
+
+ // Temporary list of windows information to provide to the input dispatcher.
+ private InputWindowList mTempInputWindows = new InputWindowList();
+
+ // Temporary input application object to provide to the input dispatcher.
+ private InputApplication mTempInputApplication = new InputApplication();
+
+ // Set to true when the first input device configuration change notification
+ // is received to indicate that the input devices are ready.
+ private final Object mInputDevicesReadyMonitor = new Object();
+ private boolean mInputDevicesReady;
+
+ public InputMonitor(WindowManagerService service) {
+ mService = service;
+ }
+
+ /* Notifies the window manager about a broken input channel.
+ *
+ * Called by the InputManager.
+ */
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ if (inputWindowHandle == null) {
+ return;
+ }
+
+ synchronized (mService.mWindowMap) {
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
+ Slog.i(WindowManagerService.TAG, "WINDOW DIED " + windowState);
+ mService.removeWindowLocked(windowState.mSession, windowState);
+ }
+ }
+
+ /* Notifies the window manager about an application that is not responding.
+ * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
+ *
+ * Called by the InputManager.
+ */
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle) {
+ AppWindowToken appWindowToken = null;
+ if (inputWindowHandle != null) {
+ synchronized (mService.mWindowMap) {
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
+ if (windowState != null) {
+ Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to "
+ + windowState.mAttrs.getTitle());
+ appWindowToken = windowState.mAppToken;
+ }
+ }
+ }
+
+ if (appWindowToken == null && inputApplicationHandle != null) {
+ appWindowToken = inputApplicationHandle.appWindowToken;
+ Slog.i(WindowManagerService.TAG, "Input event dispatching timed out sending to application "
+ + appWindowToken.stringName);
+ }
+
+ if (appWindowToken != null && appWindowToken.appToken != null) {
+ try {
+ // Notify the activity manager about the timeout and let it decide whether
+ // to abort dispatching or keep waiting.
+ boolean abort = appWindowToken.appToken.keyDispatchingTimedOut();
+ if (! abort) {
+ // The activity manager declined to abort dispatching.
+ // Wait a bit longer and timeout again later.
+ return appWindowToken.inputDispatchingTimeoutNanos;
+ }
+ } catch (RemoteException ex) {
+ }
+ }
+ return 0; // abort dispatching
+ }
+
+ private void addDragInputWindowLw(InputWindowList windowList) {
+ final InputWindow inputWindow = windowList.add();
+ inputWindow.inputChannel = mService.mDragState.mServerChannel;
+ inputWindow.name = "drag";
+ inputWindow.layoutParamsFlags = 0;
+ inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
+ inputWindow.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ inputWindow.visible = true;
+ inputWindow.canReceiveKeys = false;
+ inputWindow.hasFocus = true;
+ inputWindow.hasWallpaper = false;
+ inputWindow.paused = false;
+ inputWindow.layer = mService.mDragState.getDragLayerLw();
+ inputWindow.ownerPid = Process.myPid();
+ inputWindow.ownerUid = Process.myUid();
+
+ // The drag window covers the entire display
+ inputWindow.frameLeft = 0;
+ inputWindow.frameTop = 0;
+ inputWindow.frameRight = mService.mDisplay.getWidth();
+ inputWindow.frameBottom = mService.mDisplay.getHeight();
+
+ // The drag window cannot receive new touches.
+ inputWindow.touchableRegion.setEmpty();
+ }
+
+ public void setUpdateInputWindowsNeededLw() {
+ mUpdateInputWindowsNeeded = true;
+ }
+
+ /* Updates the cached window information provided to the input dispatcher. */
+ public void updateInputWindowsLw(boolean force) {
+ if (!force && !mUpdateInputWindowsNeeded) {
+ return;
+ }
+ mUpdateInputWindowsNeeded = false;
+
+ // Populate the input window list with information about all of the windows that
+ // could potentially receive input.
+ // 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 ArrayList<WindowState> windows = mService.mWindows;
+
+ // If there's a drag in flight, provide a pseudowindow to catch drag input
+ final boolean inDrag = (mService.mDragState != null);
+ if (inDrag) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Log.d(WindowManagerService.TAG, "Inserting drag window");
+ }
+ addDragInputWindowLw(mTempInputWindows);
+ }
+
+ final int N = windows.size();
+ for (int i = N - 1; i >= 0; i--) {
+ final WindowState child = windows.get(i);
+ if (child.mInputChannel == null || child.mRemoved) {
+ // Skip this window because it cannot possibly receive input.
+ continue;
+ }
+
+ final int flags = child.mAttrs.flags;
+ final int type = child.mAttrs.type;
+
+ final boolean hasFocus = (child == mInputFocus);
+ final boolean isVisible = child.isVisibleLw();
+ final boolean hasWallpaper = (child == mService.mWallpaperTarget)
+ && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+
+ // If there's a drag in progress and 'child' is a potential drop target,
+ // make sure it's been told about the drag
+ if (inDrag && isVisible) {
+ mService.mDragState.sendDragStartedIfNeededLw(child);
+ }
+
+ // Add a window to our list of input windows.
+ final InputWindow inputWindow = mTempInputWindows.add();
+ inputWindow.inputWindowHandle = child.mInputWindowHandle;
+ inputWindow.inputChannel = child.mInputChannel;
+ inputWindow.name = child.toString();
+ inputWindow.layoutParamsFlags = flags;
+ inputWindow.layoutParamsType = type;
+ inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
+ inputWindow.visible = isVisible;
+ inputWindow.canReceiveKeys = child.canReceiveKeys();
+ inputWindow.hasFocus = hasFocus;
+ inputWindow.hasWallpaper = hasWallpaper;
+ inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
+ inputWindow.layer = child.mLayer;
+ inputWindow.ownerPid = child.mSession.mPid;
+ inputWindow.ownerUid = child.mSession.mUid;
+
+ final Rect frame = child.mFrame;
+ inputWindow.frameLeft = frame.left;
+ inputWindow.frameTop = frame.top;
+ inputWindow.frameRight = frame.right;
+ inputWindow.frameBottom = frame.bottom;
+
+ child.getTouchableRegion(inputWindow.touchableRegion);
+ }
+
+ // Send windows to native code.
+ mService.mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
+
+ // Clear the list in preparation for the next round.
+ // Also avoids keeping InputChannel objects referenced unnecessarily.
+ mTempInputWindows.clear();
+ }
+
+ /* Notifies that the input device configuration has changed. */
+ public void notifyConfigurationChanged() {
+ mService.sendNewConfiguration();
+
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ mInputDevicesReady = true;
+ mInputDevicesReadyMonitor.notifyAll();
+ }
+ }
+ }
+
+ /* Waits until the built-in input devices have been configured. */
+ public boolean waitForInputDevicesReady(long timeoutMillis) {
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ try {
+ mInputDevicesReadyMonitor.wait(timeoutMillis);
+ } catch (InterruptedException ex) {
+ }
+ }
+ return mInputDevicesReady;
+ }
+ }
+
+ /* Notifies that the lid switch changed state. */
+ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+ mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
+ }
+
+ /* Provides an opportunity for the window manager policy to intercept early key
+ * processing as soon as the key has been read from the device. */
+ public int interceptKeyBeforeQueueing(
+ KeyEvent event, int policyFlags, boolean isScreenOn) {
+ return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
+ }
+
+ /* Provides an opportunity for the window manager policy to process a key before
+ * ordinary dispatch. */
+ public boolean interceptKeyBeforeDispatching(
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
+ }
+
+ /* Provides an opportunity for the window manager policy to process a key that
+ * the application did not handle. */
+ public KeyEvent dispatchUnhandledKey(
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
+ }
+
+ /* Called when the current input focus changes.
+ * Layer assignment is assumed to be complete by the time this is called.
+ */
+ public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.d(WindowManagerService.TAG, "Input focus has changed to " + newWindow);
+ }
+
+ if (newWindow != mInputFocus) {
+ if (newWindow != null && newWindow.canReceiveKeys()) {
+ // Displaying a window implicitly causes dispatching to be unpaused.
+ // This is to protect against bugs if someone pauses dispatching but
+ // forgets to resume.
+ newWindow.mToken.paused = false;
+ }
+
+ mInputFocus = newWindow;
+ setUpdateInputWindowsNeededLw();
+
+ if (updateInputWindows) {
+ updateInputWindowsLw(false /*force*/);
+ }
+ }
+ }
+
+ public void setFocusedAppLw(AppWindowToken newApp) {
+ // Focused app has changed.
+ if (newApp == null) {
+ mService.mInputManager.setFocusedApplication(null);
+ } else {
+ mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
+ mTempInputApplication.name = newApp.toString();
+ mTempInputApplication.dispatchingTimeoutNanos =
+ newApp.inputDispatchingTimeoutNanos;
+
+ mService.mInputManager.setFocusedApplication(mTempInputApplication);
+
+ mTempInputApplication.recycle();
+ }
+ }
+
+ public void pauseDispatchingLw(WindowToken window) {
+ if (! window.paused) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.v(WindowManagerService.TAG, "Pausing WindowToken " + window);
+ }
+
+ window.paused = true;
+ updateInputWindowsLw(true /*force*/);
+ }
+ }
+
+ public void resumeDispatchingLw(WindowToken window) {
+ if (window.paused) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.v(WindowManagerService.TAG, "Resuming WindowToken " + window);
+ }
+
+ window.paused = false;
+ updateInputWindowsLw(true /*force*/);
+ }
+ }
+
+ public void freezeInputDispatchingLw() {
+ if (! mInputDispatchFrozen) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.v(WindowManagerService.TAG, "Freezing input dispatching");
+ }
+
+ mInputDispatchFrozen = true;
+ updateInputDispatchModeLw();
+ }
+ }
+
+ public void thawInputDispatchingLw() {
+ if (mInputDispatchFrozen) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.v(WindowManagerService.TAG, "Thawing input dispatching");
+ }
+
+ mInputDispatchFrozen = false;
+ updateInputDispatchModeLw();
+ }
+ }
+
+ public void setEventDispatchingLw(boolean enabled) {
+ if (mInputDispatchEnabled != enabled) {
+ if (WindowManagerService.DEBUG_INPUT) {
+ Slog.v(WindowManagerService.TAG, "Setting event dispatching to " + enabled);
+ }
+
+ mInputDispatchEnabled = enabled;
+ updateInputDispatchModeLw();
+ }
+ }
+
+ private void updateInputDispatchModeLw() {
+ mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index fc9f10e..4356ce5 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-package com.android.server.wm; // TODO: use com.android.server.wm, once things move there
-
+package com.android.server.wm;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
new file mode 100644
index 0000000..b9db177
--- /dev/null
+++ b/services/java/com/android/server/wm/Session.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.server.wm.WindowManagerService.H;
+
+import android.content.ClipData;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.IWindow;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.Surface;
+import android.view.SurfaceSession;
+import android.view.WindowManager;
+
+import java.io.PrintWriter;
+
+/**
+ * This class represents an active client session. There is generally one
+ * Session object per process that is interacting with the window manager.
+ */
+final class Session extends IWindowSession.Stub
+ implements IBinder.DeathRecipient {
+ final WindowManagerService mService;
+ final IInputMethodClient mClient;
+ final IInputContext mInputContext;
+ final int mUid;
+ final int mPid;
+ final String mStringName;
+ SurfaceSession mSurfaceSession;
+ int mNumWindow = 0;
+ boolean mClientDead = false;
+
+ public Session(WindowManagerService service, IInputMethodClient client,
+ IInputContext inputContext) {
+ mService = service;
+ mClient = client;
+ mInputContext = inputContext;
+ mUid = Binder.getCallingUid();
+ mPid = Binder.getCallingPid();
+ StringBuilder sb = new StringBuilder();
+ sb.append("Session{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" uid ");
+ sb.append(mUid);
+ sb.append("}");
+ mStringName = sb.toString();
+
+ synchronized (mService.mWindowMap) {
+ if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
+ IBinder b = ServiceManager.getService(
+ Context.INPUT_METHOD_SERVICE);
+ mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
+ }
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ // Note: it is safe to call in to the input method manager
+ // here because we are not holding our lock.
+ if (mService.mInputMethodManager != null) {
+ mService.mInputMethodManager.addClient(client, inputContext,
+ mUid, mPid);
+ } else {
+ client.setUsingInputMethod(false);
+ }
+ client.asBinder().linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ // The caller has died, so we can just forget about this.
+ try {
+ if (mService.mInputMethodManager != null) {
+ mService.mInputMethodManager.removeClient(client);
+ }
+ } catch (RemoteException ee) {
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (RuntimeException e) {
+ // Log all 'real' exceptions thrown to the caller
+ if (!(e instanceof SecurityException)) {
+ Slog.e(WindowManagerService.TAG, "Window Session Crash", e);
+ }
+ throw e;
+ }
+ }
+
+ public void binderDied() {
+ // Note: it is safe to call in to the input method manager
+ // here because we are not holding our lock.
+ try {
+ if (mService.mInputMethodManager != null) {
+ mService.mInputMethodManager.removeClient(mClient);
+ }
+ } catch (RemoteException e) {
+ }
+ synchronized(mService.mWindowMap) {
+ mClient.asBinder().unlinkToDeath(this, 0);
+ mClientDead = true;
+ killSessionLocked();
+ }
+ }
+
+ public int add(IWindow window, WindowManager.LayoutParams attrs,
+ int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
+ return mService.addWindow(this, window, attrs, viewVisibility, outContentInsets,
+ outInputChannel);
+ }
+
+ public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
+ int viewVisibility, Rect outContentInsets) {
+ return mService.addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
+ }
+
+ public void remove(IWindow window) {
+ mService.removeWindow(this, window);
+ }
+
+ public int relayout(IWindow window, WindowManager.LayoutParams attrs,
+ int requestedWidth, int requestedHeight, int viewFlags,
+ boolean insetsPending, Rect outFrame, Rect outContentInsets,
+ Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
+ //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
+ int res = mService.relayoutWindow(this, window, attrs,
+ requestedWidth, requestedHeight, viewFlags, insetsPending,
+ outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
+ //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+ return res;
+ }
+
+ public void setTransparentRegion(IWindow window, Region region) {
+ mService.setTransparentRegionWindow(this, window, region);
+ }
+
+ public void setInsets(IWindow window, int touchableInsets,
+ Rect contentInsets, Rect visibleInsets, Region touchableArea) {
+ mService.setInsetsWindow(this, window, touchableInsets, contentInsets,
+ visibleInsets, touchableArea);
+ }
+
+ public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
+ mService.getWindowDisplayFrame(this, window, outDisplayFrame);
+ }
+
+ public void finishDrawing(IWindow window) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "IWindow finishDrawing called for " + window);
+ mService.finishDrawingWindow(this, window);
+ }
+
+ public void setInTouchMode(boolean mode) {
+ synchronized(mService.mWindowMap) {
+ mService.mInTouchMode = mode;
+ }
+ }
+
+ public boolean getInTouchMode() {
+ synchronized(mService.mWindowMap) {
+ return mService.mInTouchMode;
+ }
+ }
+
+ public boolean performHapticFeedback(IWindow window, int effectId,
+ boolean always) {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.mPolicy.performHapticFeedbackLw(
+ mService.windowForClientLocked(this, window, true),
+ effectId, always);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ /* Drag/drop */
+ public IBinder prepareDrag(IWindow window, int flags,
+ int width, int height, Surface outSurface) {
+ return mService.prepareDragSurface(window, mSurfaceSession, flags,
+ width, height, outSurface);
+ }
+
+ public boolean performDrag(IWindow window, IBinder dragToken,
+ float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+ ClipData data) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "perform drag: win=" + window + " data=" + data);
+ }
+
+ synchronized (mService.mWindowMap) {
+ if (mService.mDragState == null) {
+ Slog.w(WindowManagerService.TAG, "No drag prepared");
+ throw new IllegalStateException("performDrag() without prepareDrag()");
+ }
+
+ if (dragToken != mService.mDragState.mToken) {
+ Slog.w(WindowManagerService.TAG, "Performing mismatched drag");
+ throw new IllegalStateException("performDrag() does not match prepareDrag()");
+ }
+
+ WindowState callingWin = mService.windowForClientLocked(null, window, false);
+ if (callingWin == null) {
+ Slog.w(WindowManagerService.TAG, "Bad requesting window " + window);
+ return false; // !!! TODO: throw here?
+ }
+
+ // !!! TODO: if input is not still focused on the initiating window, fail
+ // the drag initiation (e.g. an alarm window popped up just as the application
+ // called performDrag()
+
+ mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
+
+ // !!! TODO: extract the current touch (x, y) in screen coordinates. That
+ // will let us eliminate the (touchX,touchY) parameters from the API.
+
+ // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
+ // the actual drag event dispatch stuff in the dragstate
+
+ mService.mDragState.register();
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
+ mService.mDragState.mServerChannel)) {
+ Slog.e(WindowManagerService.TAG, "Unable to transfer touch focus");
+ mService.mDragState.unregister();
+ mService.mDragState = null;
+ mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ return false;
+ }
+
+ mService.mDragState.mData = data;
+ mService.mDragState.mCurrentX = touchX;
+ mService.mDragState.mCurrentY = touchY;
+ mService.mDragState.broadcastDragStartedLw(touchX, touchY);
+
+ // remember the thumb offsets for later
+ mService.mDragState.mThumbOffsetX = thumbCenterX;
+ mService.mDragState.mThumbOffsetY = thumbCenterY;
+
+ // Make the surface visible at the proper location
+ final Surface surface = mService.mDragState.mSurface;
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
+ Surface.openTransaction();
+ try {
+ surface.setPosition((int)(touchX - thumbCenterX),
+ (int)(touchY - thumbCenterY));
+ surface.setAlpha(.7071f);
+ surface.setLayer(mService.mDragState.getDragLayerLw());
+ surface.show();
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag");
+ }
+ }
+
+ return true; // success!
+ }
+
+ public void reportDropResult(IWindow window, boolean consumed) {
+ IBinder token = window.asBinder();
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "Drop result=" + consumed + " reported by " + token);
+ }
+
+ synchronized (mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (mService.mDragState == null || mService.mDragState.mToken != token) {
+ Slog.w(WindowManagerService.TAG, "Invalid drop-result claim by " + window);
+ throw new IllegalStateException("reportDropResult() by non-recipient");
+ }
+
+ // The right window has responded, even if it's no longer around,
+ // so be sure to halt the timeout even if the later WindowState
+ // lookup fails.
+ mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
+ WindowState callingWin = mService.windowForClientLocked(null, window, false);
+ if (callingWin == null) {
+ Slog.w(WindowManagerService.TAG, "Bad result-reporting window " + window);
+ return; // !!! TODO: throw here?
+ }
+
+ mService.mDragState.mDragResult = consumed;
+ mService.mDragState.endDragLw();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ public void dragRecipientEntered(IWindow window) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "Drag into new candidate view @ " + window.asBinder());
+ }
+ }
+
+ public void dragRecipientExited(IWindow window) {
+ if (WindowManagerService.DEBUG_DRAG) {
+ Slog.d(WindowManagerService.TAG, "Drag from old candidate view @ " + window.asBinder());
+ }
+ }
+
+ public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mService.setWindowWallpaperPositionLocked(
+ mService.windowForClientLocked(this, window, true),
+ x, y, xStep, yStep);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ public void wallpaperOffsetsComplete(IBinder window) {
+ mService.wallpaperOffsetsComplete(window);
+ }
+
+ public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
+ int z, Bundle extras, boolean sync) {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.sendWindowWallpaperCommandLocked(
+ mService.windowForClientLocked(this, window, true),
+ action, x, y, z, extras, sync);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ public void wallpaperCommandComplete(IBinder window, Bundle result) {
+ mService.wallpaperCommandComplete(window, result);
+ }
+
+ void windowAddedLocked() {
+ if (mSurfaceSession == null) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "First window added to " + this + ", creating SurfaceSession");
+ mSurfaceSession = new SurfaceSession();
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+ WindowManagerService.TAG, " NEW SURFACE SESSION " + mSurfaceSession);
+ mService.mSessions.add(this);
+ }
+ mNumWindow++;
+ }
+
+ void windowRemovedLocked() {
+ mNumWindow--;
+ killSessionLocked();
+ }
+
+ void killSessionLocked() {
+ if (mNumWindow <= 0 && mClientDead) {
+ mService.mSessions.remove(this);
+ if (mSurfaceSession != null) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Last window removed from " + this
+ + ", destroying " + mSurfaceSession);
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
+ WindowManagerService.TAG, " KILL SURFACE SESSION " + mSurfaceSession);
+ try {
+ mSurfaceSession.kill();
+ } catch (Exception e) {
+ Slog.w(WindowManagerService.TAG, "Exception thrown when killing surface session "
+ + mSurfaceSession + " in session " + this
+ + ": " + e.toString());
+ }
+ mSurfaceSession = null;
+ }
+ }
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
+ pw.print(" mClientDead="); pw.print(mClientDead);
+ pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+ }
+
+ @Override
+ public String toString() {
+ return mStringName;
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java
new file mode 100644
index 0000000..625fcfe
--- /dev/null
+++ b/services/java/com/android/server/wm/StartingData.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+final class StartingData {
+ final String pkg;
+ final int theme;
+ final CharSequence nonLocalizedLabel;
+ final int labelRes;
+ final int icon;
+ final int windowFlags;
+
+ StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
+ int _labelRes, int _icon, int _windowFlags) {
+ pkg = _pkg;
+ theme = _theme;
+ nonLocalizedLabel = _nonLocalizedLabel;
+ labelRes = _labelRes;
+ icon = _icon;
+ windowFlags = _windowFlags;
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 2aa45ac..2c62080 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-package com.android.server.wm; // TODO: use com.android.server.wm, once things move there
+package com.android.server.wm;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.DisplayMetrics;
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
new file mode 100644
index 0000000..22126f3
--- /dev/null
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceSession;
+import android.view.Surface.OutOfResourcesException;
+
+/**
+ * Displays a watermark on top of the window manager's windows.
+ */
+class Watermark {
+ final String[] mTokens;
+ final String mText;
+ final Paint mTextPaint;
+ final int mTextWidth;
+ final int mTextHeight;
+ final int mTextAscent;
+ final int mTextDescent;
+ final int mDeltaX;
+ final int mDeltaY;
+
+ Surface mSurface;
+ int mLastDW;
+ int mLastDH;
+ boolean mDrawNeeded;
+
+ Watermark(Display display, SurfaceSession session, String[] tokens) {
+ final DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ if (false) {
+ Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
+ for (int i=0; i<tokens.length; i++) {
+ Log.i(WindowManagerService.TAG, " TOKEN #" + i + ": " + tokens[i]);
+ }
+ }
+
+ mTokens = tokens;
+
+ StringBuilder builder = new StringBuilder(32);
+ int len = mTokens[0].length();
+ len = len & ~1;
+ for (int i=0; i<len; i+=2) {
+ int c1 = mTokens[0].charAt(i);
+ int c2 = mTokens[0].charAt(i+1);
+ if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
+ else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
+ else c1 -= '0';
+ if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
+ else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
+ else c2 -= '0';
+ builder.append((char)(255-((c1*16)+c2)));
+ }
+ mText = builder.toString();
+ if (false) {
+ Log.i(WindowManagerService.TAG, "Final text: " + mText);
+ }
+
+ int fontSize = WindowManagerService.getPropertyInt(tokens, 1,
+ TypedValue.COMPLEX_UNIT_DIP, 20, dm);
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setTextSize(fontSize);
+ mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
+
+ FontMetricsInt fm = mTextPaint.getFontMetricsInt();
+ mTextWidth = (int)mTextPaint.measureText(mText);
+ mTextAscent = fm.ascent;
+ mTextDescent = fm.descent;
+ mTextHeight = fm.descent - fm.ascent;
+
+ mDeltaX = WindowManagerService.getPropertyInt(tokens, 2,
+ TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
+ mDeltaY = WindowManagerService.getPropertyInt(tokens, 3,
+ TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
+ int shadowColor = WindowManagerService.getPropertyInt(tokens, 4,
+ TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
+ int color = WindowManagerService.getPropertyInt(tokens, 5,
+ TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
+ int shadowRadius = WindowManagerService.getPropertyInt(tokens, 6,
+ TypedValue.COMPLEX_UNIT_PX, 7, dm);
+ int shadowDx = WindowManagerService.getPropertyInt(tokens, 8,
+ TypedValue.COMPLEX_UNIT_PX, 0, dm);
+ int shadowDy = WindowManagerService.getPropertyInt(tokens, 9,
+ TypedValue.COMPLEX_UNIT_PX, 0, dm);
+
+ mTextPaint.setColor(color);
+ mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
+
+ try {
+ mSurface = new Surface(session, 0,
+ "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
+ mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
+ mSurface.setPosition(0, 0);
+ mSurface.show();
+ } catch (OutOfResourcesException e) {
+ }
+ }
+
+ void positionSurface(int dw, int dh) {
+ if (mLastDW != dw || mLastDH != dh) {
+ mLastDW = dw;
+ mLastDH = dh;
+ mSurface.setSize(dw, dh);
+ mDrawNeeded = true;
+ }
+ }
+
+ void drawIfNeeded() {
+ if (mDrawNeeded) {
+ final int dw = mLastDW;
+ final int dh = mLastDH;
+
+ mDrawNeeded = false;
+ Rect dirty = new Rect(0, 0, dw, dh);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ } catch (OutOfResourcesException e) {
+ }
+ if (c != null) {
+ c.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ int deltaX = mDeltaX;
+ int deltaY = mDeltaY;
+
+ // deltaX shouldn't be close to a round fraction of our
+ // x step, or else things will line up too much.
+ int div = (dw+mTextWidth)/deltaX;
+ int rem = (dw+mTextWidth) - (div*deltaX);
+ int qdelta = deltaX/4;
+ if (rem < qdelta || rem > (deltaX-qdelta)) {
+ deltaX += deltaX/3;
+ }
+
+ int y = -mTextHeight;
+ int x = -mTextWidth;
+ while (y < (dh+mTextHeight)) {
+ c.drawText(mText, x, y, mTextPaint);
+ x += deltaX;
+ if (x >= dw) {
+ x -= (dw+mTextWidth);
+ y += deltaY;
+ }
+ }
+ mSurface.unlockCanvasAndPost(c);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3183643..a598ce9 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -22,7 +22,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -46,8 +45,6 @@
import com.android.server.EventLogTags;
import com.android.server.PowerManagerService;
import com.android.server.Watchdog;
-import com.android.server.AttributeCache.Entry;
-import com.android.server.Watchdog.Monitor;
import com.android.server.am.BatteryStatsService;
import android.Manifest;
@@ -56,8 +53,6 @@
import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
-import android.content.ClipData;
-import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -65,17 +60,12 @@
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
-import android.graphics.Typeface;
-import android.graphics.Paint.FontMetricsInt;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
@@ -104,8 +94,6 @@
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Display;
-import android.view.DragEvent;
-import android.view.Gravity;
import android.view.IApplicationToken;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
@@ -122,13 +110,10 @@
import android.view.Surface;
import android.view.SurfaceSession;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
-import android.view.Surface.OutOfResourcesException;
import android.view.WindowManager.LayoutParams;
-import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
@@ -225,7 +210,7 @@
private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
// Default input dispatching timeout in nanoseconds.
- private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
+ static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
static final int UPDATE_FOCUS_NORMAL = 0;
static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
@@ -513,336 +498,8 @@
boolean mTurnOnScreen;
- /**
- * Drag/drop state
- */
- class DragState {
- IBinder mToken;
- Surface mSurface;
- int mFlags;
- IBinder mLocalWin;
- ClipData mData;
- ClipDescription mDataDescription;
- boolean mDragResult;
- float mCurrentX, mCurrentY;
- float mThumbOffsetX, mThumbOffsetY;
- InputChannel mServerChannel, mClientChannel;
- WindowState mTargetWindow;
- ArrayList<WindowState> mNotifiedWindows;
- boolean mDragInProgress;
-
- private final Region mTmpRegion = new Region();
-
- DragState(IBinder token, Surface surface, int flags, IBinder localWin) {
- mToken = token;
- mSurface = surface;
- mFlags = flags;
- mLocalWin = localWin;
- mNotifiedWindows = new ArrayList<WindowState>();
- }
-
- void reset() {
- if (mSurface != null) {
- mSurface.destroy();
- }
- mSurface = null;
- mFlags = 0;
- mLocalWin = null;
- mToken = null;
- mData = null;
- mThumbOffsetX = mThumbOffsetY = 0;
- mNotifiedWindows = null;
- }
-
- void register() {
- if (DEBUG_DRAG) Slog.d(TAG, "registering drag input channel");
- if (mClientChannel != null) {
- Slog.e(TAG, "Duplicate register of drag input channel");
- } else {
- InputChannel[] channels = InputChannel.openInputChannelPair("drag");
- mServerChannel = channels[0];
- mClientChannel = channels[1];
- mInputManager.registerInputChannel(mServerChannel, null);
- InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
- mH.getLooper().getQueue());
- }
- }
-
- void unregister() {
- if (DEBUG_DRAG) Slog.d(TAG, "unregistering drag input channel");
- if (mClientChannel == null) {
- Slog.e(TAG, "Unregister of nonexistent drag input channel");
- } else {
- mInputManager.unregisterInputChannel(mServerChannel);
- InputQueue.unregisterInputChannel(mClientChannel);
- mClientChannel.dispose();
- mServerChannel.dispose();
- mClientChannel = null;
- mServerChannel = null;
- }
- }
-
- int getDragLayerLw() {
- return mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
- * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
- }
-
- /* call out to each visible window/session informing it about the drag
- */
- void broadcastDragStartedLw(final float touchX, final float touchY) {
- // Cache a base-class instance of the clip metadata so that parceling
- // works correctly in calling out to the apps.
- mDataDescription = (mData != null) ? mData.getDescription() : null;
- mNotifiedWindows.clear();
- mDragInProgress = true;
-
- if (DEBUG_DRAG) {
- Slog.d(TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
- }
-
- final int N = mWindows.size();
- for (int i = 0; i < N; i++) {
- sendDragStartedLw(mWindows.get(i), touchX, touchY, mDataDescription);
- }
- }
-
- /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
- * designated window is potentially a drop recipient. There are race situations
- * around DRAG_ENDED broadcast, so we make sure that once we've declared that
- * the drag has ended, we never send out another DRAG_STARTED for this drag action.
- *
- * This method clones the 'event' parameter if it's being delivered to the same
- * process, so it's safe for the caller to call recycle() on the event afterwards.
- */
- private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
- ClipDescription desc) {
- // Don't actually send the event if the drag is supposed to be pinned
- // to the originating window but 'newWin' is not that window.
- if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
- final IBinder winBinder = newWin.mClient.asBinder();
- if (winBinder != mLocalWin) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "Not dispatching local DRAG_STARTED to " + newWin);
- }
- return;
- }
- }
-
- if (mDragInProgress && newWin.isPotentialDragTarget()) {
- DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
- touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
- null, desc, null, false);
- try {
- newWin.mClient.dispatchDragEvent(event);
- // track each window that we've notified that the drag is starting
- mNotifiedWindows.add(newWin);
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to drag-start window " + newWin);
- } finally {
- // if the callee was local, the dispatch has already recycled the event
- if (Process.myPid() != newWin.mSession.mPid) {
- event.recycle();
- }
- }
- }
- }
-
- /* helper - construct and send a DRAG_STARTED event only if the window has not
- * previously been notified, i.e. it became visible after the drag operation
- * was begun. This is a rare case.
- */
- private void sendDragStartedIfNeededLw(WindowState newWin) {
- if (mDragInProgress) {
- // If we have sent the drag-started, we needn't do so again
- for (WindowState ws : mNotifiedWindows) {
- if (ws == newWin) {
- return;
- }
- }
- if (DEBUG_DRAG) {
- Slog.d(TAG, "need to send DRAG_STARTED to new window " + newWin);
- }
- sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
- }
- }
-
- void broadcastDragEndedLw() {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "broadcasting DRAG_ENDED");
- }
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
- 0, 0, null, null, null, mDragResult);
- for (WindowState ws: mNotifiedWindows) {
- try {
- ws.mClient.dispatchDragEvent(evt);
- } catch (RemoteException e) {
- Slog.w(TAG, "Unable to drag-end window " + ws);
- }
- }
- mNotifiedWindows.clear();
- mDragInProgress = false;
- evt.recycle();
- }
-
- void endDragLw() {
- mDragState.broadcastDragEndedLw();
-
- // stop intercepting input
- mDragState.unregister();
- mInputMonitor.updateInputWindowsLw(true /*force*/);
-
- // free our resources and drop all the object references
- mDragState.reset();
- mDragState = null;
-
- if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-drag rotation");
- boolean changed = setRotationUncheckedLocked(
- WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
- if (changed) {
- mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
- }
- }
-
- void notifyMoveLw(float x, float y) {
- final int myPid = Process.myPid();
-
- // Move the surface to the given touch
- if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION notifyMoveLw");
- Surface.openTransaction();
- try {
- mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DRAG "
- + mSurface + ": pos=(" +
- (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
- } finally {
- Surface.closeTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
- }
-
- // Tell the affected window
- WindowState touchedWin = getTouchedWinAtPointLw(x, y);
- if (touchedWin == null) {
- if (DEBUG_DRAG) Slog.d(TAG, "No touched win at x=" + x + " y=" + y);
- return;
- }
- if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
- final IBinder touchedBinder = touchedWin.mClient.asBinder();
- if (touchedBinder != mLocalWin) {
- // This drag is pinned only to the originating window, but the drag
- // point is outside that window. Pretend it's over empty space.
- touchedWin = null;
- }
- }
- try {
- // have we dragged over a new window?
- if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "sending DRAG_EXITED to " + mTargetWindow);
- }
- // force DRAG_EXITED_EVENT if appropriate
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
- x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
- null, null, null, false);
- mTargetWindow.mClient.dispatchDragEvent(evt);
- if (myPid != mTargetWindow.mSession.mPid) {
- evt.recycle();
- }
- }
- if (touchedWin != null) {
- if (false && DEBUG_DRAG) {
- Slog.d(TAG, "sending DRAG_LOCATION to " + touchedWin);
- }
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
- x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
- null, null, null, false);
- touchedWin.mClient.dispatchDragEvent(evt);
- if (myPid != touchedWin.mSession.mPid) {
- evt.recycle();
- }
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "can't send drag notification to windows");
- }
- mTargetWindow = touchedWin;
- }
-
- // Tell the drop target about the data. Returns 'true' if we can immediately
- // dispatch the global drag-ended message, 'false' if we need to wait for a
- // result from the recipient.
- boolean notifyDropLw(float x, float y) {
- WindowState touchedWin = getTouchedWinAtPointLw(x, y);
- if (touchedWin == null) {
- // "drop" outside a valid window -- no recipient to apply a
- // timeout to, and we can send the drag-ended message immediately.
- mDragResult = false;
- return true;
- }
-
- if (DEBUG_DRAG) {
- Slog.d(TAG, "sending DROP to " + touchedWin);
- }
- final int myPid = Process.myPid();
- final IBinder token = touchedWin.mClient.asBinder();
- DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
- x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
- null, null, mData, false);
- try {
- touchedWin.mClient.dispatchDragEvent(evt);
-
- // 5 second timeout for this window to respond to the drop
- mH.removeMessages(H.DRAG_END_TIMEOUT, token);
- Message msg = mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
- mH.sendMessageDelayed(msg, 5000);
- } catch (RemoteException e) {
- Slog.w(TAG, "can't send drop notification to win " + touchedWin);
- return true;
- } finally {
- if (myPid != touchedWin.mSession.mPid) {
- evt.recycle();
- }
- }
- mToken = token;
- return false;
- }
-
- // Find the visible, touch-deliverable window under the given point
- private WindowState getTouchedWinAtPointLw(float xf, float yf) {
- WindowState touchedWin = null;
- final int x = (int) xf;
- final int y = (int) yf;
- final ArrayList<WindowState> windows = mWindows;
- final int N = windows.size();
- for (int i = N - 1; i >= 0; i--) {
- WindowState child = windows.get(i);
- final int flags = child.mAttrs.flags;
- if (!child.isVisibleLw()) {
- // not visible == don't tell about drags
- continue;
- }
- if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
- // not touchable == don't tell about drags
- continue;
- }
-
- child.getTouchableRegion(mTmpRegion);
-
- final int touchFlags = flags &
- (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
- if (mTmpRegion.contains(x, y) || touchFlags == 0) {
- // Found it
- touchedWin = child;
- break;
- }
- }
-
- return touchedWin;
- }
- }
-
DragState mDragState = null;
- private final InputHandler mDragInputHandler = new BaseInputHandler() {
+ final InputHandler mDragInputHandler = new BaseInputHandler() {
@Override
public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
boolean handled = false;
@@ -2306,7 +1963,7 @@
+ attrs.token + ". Aborting.");
return WindowManagerImpl.ADD_BAD_APP_TOKEN;
}
- token = new WindowToken(attrs.token, -1, false);
+ token = new WindowToken(this, attrs.token, -1, false);
addToken = true;
} else if (attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type <= LAST_APPLICATION_WINDOW) {
@@ -2340,7 +1997,7 @@
}
}
- win = new WindowState(session, client, token,
+ win = new WindowState(this, session, client, token,
attachedWindow, attrs, viewVisibility);
if (win.mDeathRecipient == null) {
// Client has apparently died, so there is no reason to
@@ -2638,7 +2295,7 @@
mInputMonitor.updateInputWindowsLw(true /*force*/);
}
- private static void logSurface(WindowState w, String msg, RuntimeException where) {
+ static void logSurface(WindowState w, String msg, RuntimeException where) {
String str = " SURFACE " + Integer.toHexString(w.hashCode())
+ ": " + msg + " / " + w.mAttrs.getTitle();
if (where != null) {
@@ -2648,7 +2305,7 @@
}
}
- private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
+ void setTransparentRegionWindow(Session session, IWindow client, Region region) {
long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
@@ -3102,7 +2759,7 @@
return null;
}
- private void applyEnterAnimationLocked(WindowState win) {
+ void applyEnterAnimationLocked(WindowState win) {
int transit = WindowManagerPolicy.TRANSIT_SHOW;
if (win.mEnterAnimationPending) {
win.mEnterAnimationPending = false;
@@ -3112,7 +2769,7 @@
applyAnimationLocked(win, transit, true);
}
- private boolean applyAnimationLocked(WindowState win,
+ boolean applyAnimationLocked(WindowState win,
int transit, boolean isEntrance) {
if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
@@ -3368,7 +3025,7 @@
Slog.w(TAG, "Attempted to add existing input method token: " + token);
return;
}
- wtoken = new WindowToken(token, type, true);
+ wtoken = new WindowToken(this, token, type, true);
mTokenMap.put(token, wtoken);
if (type == TYPE_WALLPAPER) {
mWallpaperTokens.add(wtoken);
@@ -3456,7 +3113,7 @@
Slog.w(TAG, "Attempted to add existing app token: " + token);
return;
}
- wtoken = new AppWindowToken(token);
+ wtoken = new AppWindowToken(this, token);
wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
wtoken.groupId = groupId;
wtoken.appFullscreen = fullscreen;
@@ -5584,7 +5241,7 @@
parameters = "";
}
- final WindowManagerService.WindowState window = findWindow(hashCode);
+ final WindowState window = findWindow(hashCode);
if (window == null) {
return false;
}
@@ -5895,7 +5552,7 @@
outSurface.copyFrom(surface);
final IBinder winBinder = window.asBinder();
token = new Binder();
- mDragState = new DragState(token, surface, /*flags*/ 0, winBinder);
+ mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
mDragState.mSurface = surface;
token = mDragState.mToken = new Binder();
@@ -5925,355 +5582,8 @@
// Input Events and Focus Management
// -------------------------------------------------------------
- InputMonitor mInputMonitor = new InputMonitor();
+ final InputMonitor mInputMonitor = new InputMonitor(this);
- /* Tracks the progress of input dispatch and ensures that input dispatch state
- * is kept in sync with changes in window focus, visibility, registration, and
- * other relevant Window Manager state transitions. */
- final class InputMonitor {
- // Current window with input focus for keys and other non-touch events. May be null.
- private WindowState mInputFocus;
-
- // When true, prevents input dispatch from proceeding until set to false again.
- private boolean mInputDispatchFrozen;
-
- // When true, input dispatch proceeds normally. Otherwise all events are dropped.
- private boolean mInputDispatchEnabled = true;
-
- // When true, need to call updateInputWindowsLw().
- private boolean mUpdateInputWindowsNeeded = true;
-
- // Temporary list of windows information to provide to the input dispatcher.
- private InputWindowList mTempInputWindows = new InputWindowList();
-
- // Temporary input application object to provide to the input dispatcher.
- private InputApplication mTempInputApplication = new InputApplication();
-
- // Set to true when the first input device configuration change notification
- // is received to indicate that the input devices are ready.
- private final Object mInputDevicesReadyMonitor = new Object();
- private boolean mInputDevicesReady;
-
- /* Notifies the window manager about a broken input channel.
- *
- * Called by the InputManager.
- */
- public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
- if (inputWindowHandle == null) {
- return;
- }
-
- synchronized (mWindowMap) {
- WindowState windowState = (WindowState) inputWindowHandle.windowState;
- Slog.i(TAG, "WINDOW DIED " + windowState);
- removeWindowLocked(windowState.mSession, windowState);
- }
- }
-
- /* Notifies the window manager about an application that is not responding.
- * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
- *
- * Called by the InputManager.
- */
- public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle) {
- AppWindowToken appWindowToken = null;
- if (inputWindowHandle != null) {
- synchronized (mWindowMap) {
- WindowState windowState = (WindowState) inputWindowHandle.windowState;
- if (windowState != null) {
- Slog.i(TAG, "Input event dispatching timed out sending to "
- + windowState.mAttrs.getTitle());
- appWindowToken = windowState.mAppToken;
- }
- }
- }
-
- if (appWindowToken == null && inputApplicationHandle != null) {
- appWindowToken = inputApplicationHandle.appWindowToken;
- Slog.i(TAG, "Input event dispatching timed out sending to application "
- + appWindowToken.stringName);
- }
-
- if (appWindowToken != null && appWindowToken.appToken != null) {
- try {
- // Notify the activity manager about the timeout and let it decide whether
- // to abort dispatching or keep waiting.
- boolean abort = appWindowToken.appToken.keyDispatchingTimedOut();
- if (! abort) {
- // The activity manager declined to abort dispatching.
- // Wait a bit longer and timeout again later.
- return appWindowToken.inputDispatchingTimeoutNanos;
- }
- } catch (RemoteException ex) {
- }
- }
- return 0; // abort dispatching
- }
-
- private void addDragInputWindowLw(InputWindowList windowList) {
- final InputWindow inputWindow = windowList.add();
- inputWindow.inputChannel = mDragState.mServerChannel;
- inputWindow.name = "drag";
- inputWindow.layoutParamsFlags = 0;
- inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
- inputWindow.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- inputWindow.visible = true;
- inputWindow.canReceiveKeys = false;
- inputWindow.hasFocus = true;
- inputWindow.hasWallpaper = false;
- inputWindow.paused = false;
- inputWindow.layer = mDragState.getDragLayerLw();
- inputWindow.ownerPid = Process.myPid();
- inputWindow.ownerUid = Process.myUid();
-
- // The drag window covers the entire display
- inputWindow.frameLeft = 0;
- inputWindow.frameTop = 0;
- inputWindow.frameRight = mDisplay.getWidth();
- inputWindow.frameBottom = mDisplay.getHeight();
-
- // The drag window cannot receive new touches.
- inputWindow.touchableRegion.setEmpty();
- }
-
- public void setUpdateInputWindowsNeededLw() {
- mUpdateInputWindowsNeeded = true;
- }
-
- /* Updates the cached window information provided to the input dispatcher. */
- public void updateInputWindowsLw(boolean force) {
- if (!force && !mUpdateInputWindowsNeeded) {
- return;
- }
- mUpdateInputWindowsNeeded = false;
-
- // Populate the input window list with information about all of the windows that
- // could potentially receive input.
- // 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 ArrayList<WindowState> windows = mWindows;
-
- // If there's a drag in flight, provide a pseudowindow to catch drag input
- final boolean inDrag = (mDragState != null);
- if (inDrag) {
- if (DEBUG_DRAG) {
- Log.d(TAG, "Inserting drag window");
- }
- addDragInputWindowLw(mTempInputWindows);
- }
-
- final int N = windows.size();
- for (int i = N - 1; i >= 0; i--) {
- final WindowState child = windows.get(i);
- if (child.mInputChannel == null || child.mRemoved) {
- // Skip this window because it cannot possibly receive input.
- continue;
- }
-
- final int flags = child.mAttrs.flags;
- final int type = child.mAttrs.type;
-
- final boolean hasFocus = (child == mInputFocus);
- final boolean isVisible = child.isVisibleLw();
- final boolean hasWallpaper = (child == mWallpaperTarget)
- && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
-
- // If there's a drag in progress and 'child' is a potential drop target,
- // make sure it's been told about the drag
- if (inDrag && isVisible) {
- mDragState.sendDragStartedIfNeededLw(child);
- }
-
- // Add a window to our list of input windows.
- final InputWindow inputWindow = mTempInputWindows.add();
- inputWindow.inputWindowHandle = child.mInputWindowHandle;
- inputWindow.inputChannel = child.mInputChannel;
- inputWindow.name = child.toString();
- inputWindow.layoutParamsFlags = flags;
- inputWindow.layoutParamsType = type;
- inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
- inputWindow.visible = isVisible;
- inputWindow.canReceiveKeys = child.canReceiveKeys();
- inputWindow.hasFocus = hasFocus;
- inputWindow.hasWallpaper = hasWallpaper;
- inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
- inputWindow.layer = child.mLayer;
- inputWindow.ownerPid = child.mSession.mPid;
- inputWindow.ownerUid = child.mSession.mUid;
-
- final Rect frame = child.mFrame;
- inputWindow.frameLeft = frame.left;
- inputWindow.frameTop = frame.top;
- inputWindow.frameRight = frame.right;
- inputWindow.frameBottom = frame.bottom;
-
- child.getTouchableRegion(inputWindow.touchableRegion);
- }
-
- // Send windows to native code.
- mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
-
- // Clear the list in preparation for the next round.
- // Also avoids keeping InputChannel objects referenced unnecessarily.
- mTempInputWindows.clear();
- }
-
- /* Notifies that the input device configuration has changed. */
- public void notifyConfigurationChanged() {
- sendNewConfiguration();
-
- synchronized (mInputDevicesReadyMonitor) {
- if (!mInputDevicesReady) {
- mInputDevicesReady = true;
- mInputDevicesReadyMonitor.notifyAll();
- }
- }
- }
-
- /* Waits until the built-in input devices have been configured. */
- public boolean waitForInputDevicesReady(long timeoutMillis) {
- synchronized (mInputDevicesReadyMonitor) {
- if (!mInputDevicesReady) {
- try {
- mInputDevicesReadyMonitor.wait(timeoutMillis);
- } catch (InterruptedException ex) {
- }
- }
- return mInputDevicesReady;
- }
- }
-
- /* Notifies that the lid switch changed state. */
- public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
- mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
- }
-
- /* Provides an opportunity for the window manager policy to intercept early key
- * processing as soon as the key has been read from the device. */
- public int interceptKeyBeforeQueueing(
- KeyEvent event, int policyFlags, boolean isScreenOn) {
- return mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
- }
-
- /* Provides an opportunity for the window manager policy to process a key before
- * ordinary dispatch. */
- public boolean interceptKeyBeforeDispatching(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
- return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
- }
-
- /* Provides an opportunity for the window manager policy to process a key that
- * the application did not handle. */
- public KeyEvent dispatchUnhandledKey(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
- return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
- }
-
- /* Called when the current input focus changes.
- * Layer assignment is assumed to be complete by the time this is called.
- */
- public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
- if (DEBUG_INPUT) {
- Slog.d(TAG, "Input focus has changed to " + newWindow);
- }
-
- if (newWindow != mInputFocus) {
- if (newWindow != null && newWindow.canReceiveKeys()) {
- // Displaying a window implicitly causes dispatching to be unpaused.
- // This is to protect against bugs if someone pauses dispatching but
- // forgets to resume.
- newWindow.mToken.paused = false;
- }
-
- mInputFocus = newWindow;
- setUpdateInputWindowsNeededLw();
-
- if (updateInputWindows) {
- updateInputWindowsLw(false /*force*/);
- }
- }
- }
-
- public void setFocusedAppLw(AppWindowToken newApp) {
- // Focused app has changed.
- if (newApp == null) {
- mInputManager.setFocusedApplication(null);
- } else {
- mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
- mTempInputApplication.name = newApp.toString();
- mTempInputApplication.dispatchingTimeoutNanos =
- newApp.inputDispatchingTimeoutNanos;
-
- mInputManager.setFocusedApplication(mTempInputApplication);
-
- mTempInputApplication.recycle();
- }
- }
-
- public void pauseDispatchingLw(WindowToken window) {
- if (! window.paused) {
- if (DEBUG_INPUT) {
- Slog.v(TAG, "Pausing WindowToken " + window);
- }
-
- window.paused = true;
- updateInputWindowsLw(true /*force*/);
- }
- }
-
- public void resumeDispatchingLw(WindowToken window) {
- if (window.paused) {
- if (DEBUG_INPUT) {
- Slog.v(TAG, "Resuming WindowToken " + window);
- }
-
- window.paused = false;
- updateInputWindowsLw(true /*force*/);
- }
- }
-
- public void freezeInputDispatchingLw() {
- if (! mInputDispatchFrozen) {
- if (DEBUG_INPUT) {
- Slog.v(TAG, "Freezing input dispatching");
- }
-
- mInputDispatchFrozen = true;
- updateInputDispatchModeLw();
- }
- }
-
- public void thawInputDispatchingLw() {
- if (mInputDispatchFrozen) {
- if (DEBUG_INPUT) {
- Slog.v(TAG, "Thawing input dispatching");
- }
-
- mInputDispatchFrozen = false;
- updateInputDispatchModeLw();
- }
- }
-
- public void setEventDispatchingLw(boolean enabled) {
- if (mInputDispatchEnabled != enabled) {
- if (DEBUG_INPUT) {
- Slog.v(TAG, "Setting event dispatching to " + enabled);
- }
-
- mInputDispatchEnabled = enabled;
- updateInputDispatchModeLw();
- }
- }
-
- private void updateInputDispatchModeLw() {
- mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
- }
- }
-
public void pauseKeyDispatching(IBinder _token) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"pauseKeyDispatching()")) {
@@ -6502,2409 +5812,6 @@
mPolicy.systemReady();
}
- // -------------------------------------------------------------
- // Client Session State
- // -------------------------------------------------------------
-
- private final class Session extends IWindowSession.Stub
- implements IBinder.DeathRecipient {
- final IInputMethodClient mClient;
- final IInputContext mInputContext;
- final int mUid;
- final int mPid;
- final String mStringName;
- SurfaceSession mSurfaceSession;
- int mNumWindow = 0;
- boolean mClientDead = false;
-
- public Session(IInputMethodClient client, IInputContext inputContext) {
- mClient = client;
- mInputContext = inputContext;
- mUid = Binder.getCallingUid();
- mPid = Binder.getCallingPid();
- StringBuilder sb = new StringBuilder();
- sb.append("Session{");
- sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(" uid ");
- sb.append(mUid);
- sb.append("}");
- mStringName = sb.toString();
-
- synchronized (mWindowMap) {
- if (mInputMethodManager == null && mHaveInputMethods) {
- IBinder b = ServiceManager.getService(
- Context.INPUT_METHOD_SERVICE);
- mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
- }
- }
- long ident = Binder.clearCallingIdentity();
- try {
- // Note: it is safe to call in to the input method manager
- // here because we are not holding our lock.
- if (mInputMethodManager != null) {
- mInputMethodManager.addClient(client, inputContext,
- mUid, mPid);
- } else {
- client.setUsingInputMethod(false);
- }
- client.asBinder().linkToDeath(this, 0);
- } catch (RemoteException e) {
- // The caller has died, so we can just forget about this.
- try {
- if (mInputMethodManager != null) {
- mInputMethodManager.removeClient(client);
- }
- } catch (RemoteException ee) {
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- return super.onTransact(code, data, reply, flags);
- } catch (RuntimeException e) {
- // Log all 'real' exceptions thrown to the caller
- if (!(e instanceof SecurityException)) {
- Slog.e(TAG, "Window Session Crash", e);
- }
- throw e;
- }
- }
-
- public void binderDied() {
- // Note: it is safe to call in to the input method manager
- // here because we are not holding our lock.
- try {
- if (mInputMethodManager != null) {
- mInputMethodManager.removeClient(mClient);
- }
- } catch (RemoteException e) {
- }
- synchronized(mWindowMap) {
- mClient.asBinder().unlinkToDeath(this, 0);
- mClientDead = true;
- killSessionLocked();
- }
- }
-
- public int add(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
- return addWindow(this, window, attrs, viewVisibility, outContentInsets,
- outInputChannel);
- }
-
- public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
- int viewVisibility, Rect outContentInsets) {
- return addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
- }
-
- public void remove(IWindow window) {
- removeWindow(this, window);
- }
-
- public int relayout(IWindow window, WindowManager.LayoutParams attrs,
- int requestedWidth, int requestedHeight, int viewFlags,
- boolean insetsPending, Rect outFrame, Rect outContentInsets,
- Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
- //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
- int res = relayoutWindow(this, window, attrs,
- requestedWidth, requestedHeight, viewFlags, insetsPending,
- outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
- //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
- return res;
- }
-
- public void setTransparentRegion(IWindow window, Region region) {
- setTransparentRegionWindow(this, window, region);
- }
-
- public void setInsets(IWindow window, int touchableInsets,
- Rect contentInsets, Rect visibleInsets, Region touchableArea) {
- setInsetsWindow(this, window, touchableInsets, contentInsets,
- visibleInsets, touchableArea);
- }
-
- public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
- getWindowDisplayFrame(this, window, outDisplayFrame);
- }
-
- public void finishDrawing(IWindow window) {
- if (localLOGV) Slog.v(
- TAG, "IWindow finishDrawing called for " + window);
- finishDrawingWindow(this, window);
- }
-
- public void setInTouchMode(boolean mode) {
- synchronized(mWindowMap) {
- mInTouchMode = mode;
- }
- }
-
- public boolean getInTouchMode() {
- synchronized(mWindowMap) {
- return mInTouchMode;
- }
- }
-
- public boolean performHapticFeedback(IWindow window, int effectId,
- boolean always) {
- synchronized(mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- return mPolicy.performHapticFeedbackLw(
- windowForClientLocked(this, window, true),
- effectId, always);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- /* Drag/drop */
- public IBinder prepareDrag(IWindow window, int flags,
- int width, int height, Surface outSurface) {
- return prepareDragSurface(window, mSurfaceSession, flags,
- width, height, outSurface);
- }
-
- public boolean performDrag(IWindow window, IBinder dragToken,
- float touchX, float touchY, float thumbCenterX, float thumbCenterY,
- ClipData data) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "perform drag: win=" + window + " data=" + data);
- }
-
- synchronized (mWindowMap) {
- if (mDragState == null) {
- Slog.w(TAG, "No drag prepared");
- throw new IllegalStateException("performDrag() without prepareDrag()");
- }
-
- if (dragToken != mDragState.mToken) {
- Slog.w(TAG, "Performing mismatched drag");
- throw new IllegalStateException("performDrag() does not match prepareDrag()");
- }
-
- WindowState callingWin = windowForClientLocked(null, window, false);
- if (callingWin == null) {
- Slog.w(TAG, "Bad requesting window " + window);
- return false; // !!! TODO: throw here?
- }
-
- // !!! TODO: if input is not still focused on the initiating window, fail
- // the drag initiation (e.g. an alarm window popped up just as the application
- // called performDrag()
-
- mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
-
- // !!! TODO: extract the current touch (x, y) in screen coordinates. That
- // will let us eliminate the (touchX,touchY) parameters from the API.
-
- // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
- // the actual drag event dispatch stuff in the dragstate
-
- mDragState.register();
- mInputMonitor.updateInputWindowsLw(true /*force*/);
- if (!mInputManager.transferTouchFocus(callingWin.mInputChannel,
- mDragState.mServerChannel)) {
- Slog.e(TAG, "Unable to transfer touch focus");
- mDragState.unregister();
- mDragState = null;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
- return false;
- }
-
- mDragState.mData = data;
- mDragState.mCurrentX = touchX;
- mDragState.mCurrentY = touchY;
- mDragState.broadcastDragStartedLw(touchX, touchY);
-
- // remember the thumb offsets for later
- mDragState.mThumbOffsetX = thumbCenterX;
- mDragState.mThumbOffsetY = thumbCenterY;
-
- // Make the surface visible at the proper location
- final Surface surface = mDragState.mSurface;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performDrag");
- Surface.openTransaction();
- try {
- surface.setPosition((int)(touchX - thumbCenterX),
- (int)(touchY - thumbCenterY));
- surface.setAlpha(.7071f);
- surface.setLayer(mDragState.getDragLayerLw());
- surface.show();
- } finally {
- Surface.closeTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performDrag");
- }
- }
-
- return true; // success!
- }
-
- public void reportDropResult(IWindow window, boolean consumed) {
- IBinder token = window.asBinder();
- if (DEBUG_DRAG) {
- Slog.d(TAG, "Drop result=" + consumed + " reported by " + token);
- }
-
- synchronized (mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- if (mDragState == null || mDragState.mToken != token) {
- Slog.w(TAG, "Invalid drop-result claim by " + window);
- throw new IllegalStateException("reportDropResult() by non-recipient");
- }
-
- // The right window has responded, even if it's no longer around,
- // so be sure to halt the timeout even if the later WindowState
- // lookup fails.
- mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
- WindowState callingWin = windowForClientLocked(null, window, false);
- if (callingWin == null) {
- Slog.w(TAG, "Bad result-reporting window " + window);
- return; // !!! TODO: throw here?
- }
-
- mDragState.mDragResult = consumed;
- mDragState.endDragLw();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- public void dragRecipientEntered(IWindow window) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "Drag into new candidate view @ " + window.asBinder());
- }
- }
-
- public void dragRecipientExited(IWindow window) {
- if (DEBUG_DRAG) {
- Slog.d(TAG, "Drag from old candidate view @ " + window.asBinder());
- }
- }
-
- public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
- synchronized(mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- setWindowWallpaperPositionLocked(
- windowForClientLocked(this, window, true),
- x, y, xStep, yStep);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- public void wallpaperOffsetsComplete(IBinder window) {
- WindowManagerService.this.wallpaperOffsetsComplete(window);
- }
-
- public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
- int z, Bundle extras, boolean sync) {
- synchronized(mWindowMap) {
- long ident = Binder.clearCallingIdentity();
- try {
- return sendWindowWallpaperCommandLocked(
- windowForClientLocked(this, window, true),
- action, x, y, z, extras, sync);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- public void wallpaperCommandComplete(IBinder window, Bundle result) {
- WindowManagerService.this.wallpaperCommandComplete(window, result);
- }
-
- void windowAddedLocked() {
- if (mSurfaceSession == null) {
- if (localLOGV) Slog.v(
- TAG, "First window added to " + this + ", creating SurfaceSession");
- mSurfaceSession = new SurfaceSession();
- if (SHOW_TRANSACTIONS) Slog.i(
- TAG, " NEW SURFACE SESSION " + mSurfaceSession);
- mSessions.add(this);
- }
- mNumWindow++;
- }
-
- void windowRemovedLocked() {
- mNumWindow--;
- killSessionLocked();
- }
-
- void killSessionLocked() {
- if (mNumWindow <= 0 && mClientDead) {
- mSessions.remove(this);
- if (mSurfaceSession != null) {
- if (localLOGV) Slog.v(
- TAG, "Last window removed from " + this
- + ", destroying " + mSurfaceSession);
- if (SHOW_TRANSACTIONS) Slog.i(
- TAG, " KILL SURFACE SESSION " + mSurfaceSession);
- try {
- mSurfaceSession.kill();
- } catch (Exception e) {
- Slog.w(TAG, "Exception thrown when killing surface session "
- + mSurfaceSession + " in session " + this
- + ": " + e.toString());
- }
- mSurfaceSession = null;
- }
- }
- }
-
- void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
- pw.print(" mClientDead="); pw.print(mClientDead);
- pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
- }
-
- @Override
- public String toString() {
- return mStringName;
- }
- }
-
- // -------------------------------------------------------------
- // Client Window State
- // -------------------------------------------------------------
-
- private final class WindowState implements WindowManagerPolicy.WindowState {
- final Session mSession;
- final IWindow mClient;
- WindowToken mToken;
- WindowToken mRootToken;
- AppWindowToken mAppToken;
- AppWindowToken mTargetAppToken;
- final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
- final DeathRecipient mDeathRecipient;
- final WindowState mAttachedWindow;
- final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
- final int mBaseLayer;
- final int mSubLayer;
- final boolean mLayoutAttached;
- final boolean mIsImWindow;
- final boolean mIsWallpaper;
- final boolean mIsFloatingLayer;
- int mViewVisibility;
- boolean mPolicyVisibility = true;
- boolean mPolicyVisibilityAfterAnim = true;
- boolean mAppFreezing;
- Surface mSurface;
- boolean mReportDestroySurface;
- boolean mSurfacePendingDestroy;
- boolean mAttachedHidden; // is our parent window hidden?
- boolean mLastHidden; // was this window last hidden?
- boolean mWallpaperVisible; // for wallpaper, what was last vis report?
- int mRequestedWidth;
- int mRequestedHeight;
- int mLastRequestedWidth;
- int mLastRequestedHeight;
- int mLayer;
- int mAnimLayer;
- int mLastLayer;
- boolean mHaveFrame;
- boolean mObscured;
- boolean mTurnOnScreen;
-
- int mLayoutSeq = -1;
-
- Configuration mConfiguration = null;
-
- // Actual frame shown on-screen (may be modified by animation)
- final Rect mShownFrame = new Rect();
- final Rect mLastShownFrame = new Rect();
-
- /**
- * Set when we have changed the size of the surface, to know that
- * we must tell them application to resize (and thus redraw itself).
- */
- boolean mSurfaceResized;
-
- /**
- * Insets that determine the actually visible area
- */
- final Rect mVisibleInsets = new Rect();
- final Rect mLastVisibleInsets = new Rect();
- boolean mVisibleInsetsChanged;
-
- /**
- * Insets that are covered by system windows
- */
- final Rect mContentInsets = new Rect();
- final Rect mLastContentInsets = new Rect();
- boolean mContentInsetsChanged;
-
- /**
- * Set to true if we are waiting for this window to receive its
- * given internal insets before laying out other windows based on it.
- */
- boolean mGivenInsetsPending;
-
- /**
- * These are the content insets that were given during layout for
- * this window, to be applied to windows behind it.
- */
- final Rect mGivenContentInsets = new Rect();
-
- /**
- * These are the visible insets that were given during layout for
- * this window, to be applied to windows behind it.
- */
- final Rect mGivenVisibleInsets = new Rect();
-
- /**
- * This is the given touchable area relative to the window frame, or null if none.
- */
- final Region mGivenTouchableRegion = new Region();
-
- /**
- * Flag indicating whether the touchable region should be adjusted by
- * the visible insets; if false the area outside the visible insets is
- * NOT touchable, so we must use those to adjust the frame during hit
- * tests.
- */
- int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
-
- // Current transformation being applied.
- boolean mHaveMatrix;
- float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
- float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
- float mHScale=1, mVScale=1;
- float mLastHScale=1, mLastVScale=1;
- final Matrix mTmpMatrix = new Matrix();
-
- // "Real" frame that the application sees.
- final Rect mFrame = new Rect();
- final Rect mLastFrame = new Rect();
-
- final Rect mContainingFrame = new Rect();
- final Rect mDisplayFrame = new Rect();
- final Rect mContentFrame = new Rect();
- final Rect mParentFrame = new Rect();
- final Rect mVisibleFrame = new Rect();
-
- boolean mContentChanged;
-
- float mShownAlpha = 1;
- float mAlpha = 1;
- float mLastAlpha = 1;
-
- // Set to true if, when the window gets displayed, it should perform
- // an enter animation.
- boolean mEnterAnimationPending;
-
- // Currently running animation.
- boolean mAnimating;
- boolean mLocalAnimating;
- Animation mAnimation;
- boolean mAnimationIsEntrance;
- boolean mHasTransformation;
- boolean mHasLocalTransformation;
- final Transformation mTransformation = new Transformation();
-
- // If a window showing a wallpaper: the requested offset for the
- // wallpaper; if a wallpaper window: the currently applied offset.
- float mWallpaperX = -1;
- float mWallpaperY = -1;
-
- // If a window showing a wallpaper: what fraction of the offset
- // range corresponds to a full virtual screen.
- float mWallpaperXStep = -1;
- float mWallpaperYStep = -1;
-
- // Wallpaper windows: pixels offset based on above variables.
- int mXOffset;
- int mYOffset;
-
- // This is set after IWindowSession.relayout() has been called at
- // least once for the window. It allows us to detect the situation
- // where we don't yet have a surface, but should have one soon, so
- // we can give the window focus before waiting for the relayout.
- boolean mRelayoutCalled;
-
- // This is set after the Surface has been created but before the
- // window has been drawn. During this time the surface is hidden.
- boolean mDrawPending;
-
- // This is set after the window has finished drawing for the first
- // time but before its surface is shown. The surface will be
- // displayed when the next layout is run.
- boolean mCommitDrawPending;
-
- // This is set during the time after the window's drawing has been
- // committed, and before its surface is actually shown. It is used
- // to delay showing the surface until all windows in a token are ready
- // to be shown.
- boolean mReadyToShow;
-
- // Set when the window has been shown in the screen the first time.
- boolean mHasDrawn;
-
- // Currently running an exit animation?
- boolean mExiting;
-
- // Currently on the mDestroySurface list?
- boolean mDestroying;
-
- // Completely remove from window manager after exit animation?
- boolean mRemoveOnExit;
-
- // Set when the orientation is changing and this window has not yet
- // been updated for the new orientation.
- boolean mOrientationChanging;
-
- // Is this window now (or just being) removed?
- boolean mRemoved;
-
- // Temp for keeping track of windows that have been removed when
- // rebuilding window list.
- boolean mRebuilding;
-
- // For debugging, this is the last information given to the surface flinger.
- boolean mSurfaceShown;
- int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
- int mSurfaceLayer;
- float mSurfaceAlpha;
-
- // Input channel and input window handle used by the input dispatcher.
- InputWindowHandle mInputWindowHandle;
- InputChannel mInputChannel;
-
- // Used to improve performance of toString()
- String mStringNameCache;
- CharSequence mLastTitle;
- boolean mWasPaused;
-
- WindowState(Session s, IWindow c, WindowToken token,
- WindowState attachedWindow, WindowManager.LayoutParams a,
- int viewVisibility) {
- mSession = s;
- mClient = c;
- mToken = token;
- mAttrs.copyFrom(a);
- mViewVisibility = viewVisibility;
- DeathRecipient deathRecipient = new DeathRecipient();
- mAlpha = a.alpha;
- if (localLOGV) Slog.v(
- TAG, "Window " + this + " client=" + c.asBinder()
- + " token=" + token + " (" + mAttrs.token + ")");
- try {
- c.asBinder().linkToDeath(deathRecipient, 0);
- } catch (RemoteException e) {
- mDeathRecipient = null;
- mAttachedWindow = null;
- mLayoutAttached = false;
- mIsImWindow = false;
- mIsWallpaper = false;
- mIsFloatingLayer = false;
- mBaseLayer = 0;
- mSubLayer = 0;
- return;
- }
- mDeathRecipient = deathRecipient;
-
- if ((mAttrs.type >= FIRST_SUB_WINDOW &&
- mAttrs.type <= LAST_SUB_WINDOW)) {
- // The multiplier here is to reserve space for multiple
- // windows in the same type layer.
- mBaseLayer = mPolicy.windowTypeToLayerLw(
- attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
- mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
- mAttachedWindow = attachedWindow;
- if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
- mAttachedWindow.mChildWindows.add(this);
- mLayoutAttached = mAttrs.type !=
- WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
- mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
- || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
- mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
- mIsFloatingLayer = mIsImWindow || mIsWallpaper;
- } else {
- // The multiplier here is to reserve space for multiple
- // windows in the same type layer.
- mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
- * TYPE_LAYER_MULTIPLIER
- + TYPE_LAYER_OFFSET;
- mSubLayer = 0;
- mAttachedWindow = null;
- mLayoutAttached = false;
- mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
- || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
- mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
- mIsFloatingLayer = mIsImWindow || mIsWallpaper;
- }
-
- WindowState appWin = this;
- while (appWin.mAttachedWindow != null) {
- appWin = mAttachedWindow;
- }
- WindowToken appToken = appWin.mToken;
- while (appToken.appWindowToken == null) {
- WindowToken parent = mTokenMap.get(appToken.token);
- if (parent == null || appToken == parent) {
- break;
- }
- appToken = parent;
- }
- mRootToken = appToken;
- mAppToken = appToken.appWindowToken;
-
- mSurface = null;
- mRequestedWidth = 0;
- mRequestedHeight = 0;
- mLastRequestedWidth = 0;
- mLastRequestedHeight = 0;
- mXOffset = 0;
- mYOffset = 0;
- mLayer = 0;
- mAnimLayer = 0;
- mLastLayer = 0;
- mInputWindowHandle = new InputWindowHandle(
- mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
- }
-
- void attach() {
- if (localLOGV) Slog.v(
- TAG, "Attaching " + this + " token=" + mToken
- + ", list=" + mToken.windows);
- mSession.windowAddedLocked();
- }
-
- public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
- mHaveFrame = true;
-
- final Rect container = mContainingFrame;
- container.set(pf);
-
- final Rect display = mDisplayFrame;
- display.set(df);
-
- if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
- container.intersect(mCompatibleScreenFrame);
- if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
- display.intersect(mCompatibleScreenFrame);
- }
- }
-
- final int pw = container.right - container.left;
- final int ph = container.bottom - container.top;
-
- int w,h;
- if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
- w = mAttrs.width < 0 ? pw : mAttrs.width;
- h = mAttrs.height< 0 ? ph : mAttrs.height;
- } else {
- w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
- h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
- }
-
- if (!mParentFrame.equals(pf)) {
- //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
- // + " to " + pf);
- mParentFrame.set(pf);
- mContentChanged = true;
- }
-
- final Rect content = mContentFrame;
- content.set(cf);
-
- final Rect visible = mVisibleFrame;
- visible.set(vf);
-
- final Rect frame = mFrame;
- final int fw = frame.width();
- final int fh = frame.height();
-
- //System.out.println("In: w=" + w + " h=" + h + " container=" +
- // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
-
- Gravity.apply(mAttrs.gravity, w, h, container,
- (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
- (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
-
- //System.out.println("Out: " + mFrame);
-
- // Now make sure the window fits in the overall display.
- Gravity.applyDisplay(mAttrs.gravity, df, frame);
-
- // Make sure the content and visible frames are inside of the
- // final window frame.
- if (content.left < frame.left) content.left = frame.left;
- if (content.top < frame.top) content.top = frame.top;
- if (content.right > frame.right) content.right = frame.right;
- if (content.bottom > frame.bottom) content.bottom = frame.bottom;
- if (visible.left < frame.left) visible.left = frame.left;
- if (visible.top < frame.top) visible.top = frame.top;
- if (visible.right > frame.right) visible.right = frame.right;
- if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
-
- final Rect contentInsets = mContentInsets;
- contentInsets.left = content.left-frame.left;
- contentInsets.top = content.top-frame.top;
- contentInsets.right = frame.right-content.right;
- contentInsets.bottom = frame.bottom-content.bottom;
-
- final Rect visibleInsets = mVisibleInsets;
- visibleInsets.left = visible.left-frame.left;
- visibleInsets.top = visible.top-frame.top;
- visibleInsets.right = frame.right-visible.right;
- visibleInsets.bottom = frame.bottom-visible.bottom;
-
- if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
- updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
- mDisplay.getHeight(), false);
- }
-
- if (localLOGV) {
- //if ("com.google.android.youtube".equals(mAttrs.packageName)
- // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- Slog.v(TAG, "Resolving (mRequestedWidth="
- + mRequestedWidth + ", mRequestedheight="
- + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
- + "): frame=" + mFrame.toShortString()
- + " ci=" + contentInsets.toShortString()
- + " vi=" + visibleInsets.toShortString());
- //}
- }
- }
-
- public Rect getFrameLw() {
- return mFrame;
- }
-
- public Rect getShownFrameLw() {
- return mShownFrame;
- }
-
- public Rect getDisplayFrameLw() {
- return mDisplayFrame;
- }
-
- public Rect getContentFrameLw() {
- return mContentFrame;
- }
-
- public Rect getVisibleFrameLw() {
- return mVisibleFrame;
- }
-
- public boolean getGivenInsetsPendingLw() {
- return mGivenInsetsPending;
- }
-
- public Rect getGivenContentInsetsLw() {
- return mGivenContentInsets;
- }
-
- public Rect getGivenVisibleInsetsLw() {
- return mGivenVisibleInsets;
- }
-
- public WindowManager.LayoutParams getAttrs() {
- return mAttrs;
- }
-
- public int getSurfaceLayer() {
- return mLayer;
- }
-
- public IApplicationToken getAppToken() {
- return mAppToken != null ? mAppToken.appToken : null;
- }
-
- public long getInputDispatchingTimeoutNanos() {
- return mAppToken != null
- ? mAppToken.inputDispatchingTimeoutNanos
- : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- }
-
- public boolean hasAppShownWindows() {
- return mAppToken != null ? mAppToken.firstWindowDrawn : false;
- }
-
- public void setAnimation(Animation anim) {
- if (localLOGV) Slog.v(
- TAG, "Setting animation in " + this + ": " + anim);
- mAnimating = false;
- mLocalAnimating = false;
- mAnimation = anim;
- mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
- mAnimation.scaleCurrentDuration(mWindowAnimationScale);
- }
-
- public void clearAnimation() {
- if (mAnimation != null) {
- mAnimating = true;
- mLocalAnimating = false;
- mAnimation.cancel();
- mAnimation = null;
- }
- }
-
- Surface createSurfaceLocked() {
- if (mSurface == null) {
- mReportDestroySurface = false;
- mSurfacePendingDestroy = false;
- mDrawPending = true;
- mCommitDrawPending = false;
- mReadyToShow = false;
- if (mAppToken != null) {
- mAppToken.allDrawn = false;
- }
-
- int flags = 0;
-
- if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
- flags |= Surface.SECURE;
- }
- if (DEBUG_VISIBILITY) Slog.v(
- TAG, "Creating surface in session "
- + mSession.mSurfaceSession + " window " + this
- + " w=" + mFrame.width()
- + " h=" + mFrame.height() + " format="
- + mAttrs.format + " flags=" + flags);
-
- int w = mFrame.width();
- int h = mFrame.height();
- if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
- // for a scaled surface, we always want the requested
- // size.
- w = mRequestedWidth;
- h = mRequestedHeight;
- }
-
- // Something is wrong and SurfaceFlinger will not like this,
- // try to revert to sane values
- if (w <= 0) w = 1;
- if (h <= 0) h = 1;
-
- mSurfaceShown = false;
- mSurfaceLayer = 0;
- mSurfaceAlpha = 1;
- mSurfaceX = 0;
- mSurfaceY = 0;
- mSurfaceW = w;
- mSurfaceH = h;
- try {
- final boolean isHwAccelerated = (mAttrs.flags &
- WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
- final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
- if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) {
- flags |= Surface.OPAQUE;
- }
- mSurface = new Surface(
- mSession.mSurfaceSession, mSession.mPid,
- mAttrs.getTitle().toString(),
- 0, w, h, format, flags);
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
- + mSurface + " IN SESSION "
- + mSession.mSurfaceSession
- + ": pid=" + mSession.mPid + " format="
- + mAttrs.format + " flags=0x"
- + Integer.toHexString(flags)
- + " / " + this);
- } catch (Surface.OutOfResourcesException e) {
- Slog.w(TAG, "OutOfResourcesException creating surface");
- reclaimSomeSurfaceMemoryLocked(this, "create");
- return null;
- } catch (Exception e) {
- Slog.e(TAG, "Exception creating surface", e);
- return null;
- }
-
- if (localLOGV) Slog.v(
- TAG, "Got surface: " + mSurface
- + ", set left=" + mFrame.left + " top=" + mFrame.top
- + ", animLayer=" + mAnimLayer);
- if (SHOW_TRANSACTIONS) {
- Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
- logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
- mFrame.width() + "x" + mFrame.height() + "), layer=" +
- mAnimLayer + " HIDE", null);
- }
- Surface.openTransaction();
- try {
- try {
- mSurfaceX = mFrame.left + mXOffset;
- mSurfaceY = mFrame.top + mYOffset;
- mSurface.setPosition(mSurfaceX, mSurfaceY);
- mSurfaceLayer = mAnimLayer;
- mSurface.setLayer(mAnimLayer);
- mSurfaceShown = false;
- mSurface.hide();
- if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
- if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
- mSurface.setFlags(Surface.SURFACE_DITHER,
- Surface.SURFACE_DITHER);
- }
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error creating surface in " + w, e);
- reclaimSomeSurfaceMemoryLocked(this, "create-init");
- }
- mLastHidden = true;
- } finally {
- Surface.closeTransaction();
- if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
- }
- if (localLOGV) Slog.v(
- TAG, "Created surface " + this);
- }
- return mSurface;
- }
-
- void destroySurfaceLocked() {
- if (mAppToken != null && this == mAppToken.startingWindow) {
- mAppToken.startingDisplayed = false;
- }
-
- if (mSurface != null) {
- mDrawPending = false;
- mCommitDrawPending = false;
- mReadyToShow = false;
-
- int i = mChildWindows.size();
- while (i > 0) {
- i--;
- WindowState c = mChildWindows.get(i);
- c.mAttachedHidden = true;
- }
-
- if (mReportDestroySurface) {
- mReportDestroySurface = false;
- mSurfacePendingDestroy = true;
- try {
- mClient.dispatchGetNewSurface();
- // We'll really destroy on the next time around.
- return;
- } catch (RemoteException e) {
- }
- }
-
- try {
- if (DEBUG_VISIBILITY) {
- RuntimeException e = null;
- if (!HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.w(TAG, "Window " + this + " destroying surface "
- + mSurface + ", session " + mSession, e);
- }
- if (SHOW_TRANSACTIONS) {
- RuntimeException e = null;
- if (!HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
- }
- mSurface.destroy();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Exception thrown when destroying Window " + this
- + " surface " + mSurface + " session " + mSession
- + ": " + e.toString());
- }
-
- mSurfaceShown = false;
- mSurface = null;
- }
- }
-
- boolean finishDrawingLocked() {
- if (mDrawPending) {
- if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
- TAG, "finishDrawingLocked: " + mSurface);
- mCommitDrawPending = true;
- mDrawPending = false;
- return true;
- }
- return false;
- }
-
- // This must be called while inside a transaction.
- boolean commitFinishDrawingLocked(long currentTime) {
- //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
- if (!mCommitDrawPending) {
- return false;
- }
- mCommitDrawPending = false;
- mReadyToShow = true;
- final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
- final AppWindowToken atoken = mAppToken;
- if (atoken == null || atoken.allDrawn || starting) {
- performShowLocked();
- }
- return true;
- }
-
- // This must be called while inside a transaction.
- boolean performShowLocked() {
- if (DEBUG_VISIBILITY) {
- RuntimeException e = null;
- if (!HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.v(TAG, "performShow on " + this
- + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
- + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
- }
- if (mReadyToShow && isReadyForDisplay()) {
- if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
- "SHOW (performShowLocked)", null);
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
- + " during animation: policyVis=" + mPolicyVisibility
- + " attHidden=" + mAttachedHidden
- + " tok.hiddenRequested="
- + (mAppToken != null ? mAppToken.hiddenRequested : false)
- + " tok.hidden="
- + (mAppToken != null ? mAppToken.hidden : false)
- + " animating=" + mAnimating
- + " tok animating="
- + (mAppToken != null ? mAppToken.animating : false));
- if (!showSurfaceRobustlyLocked(this)) {
- return false;
- }
- mLastAlpha = -1;
- mHasDrawn = true;
- mLastHidden = false;
- mReadyToShow = false;
- enableScreenIfNeededLocked();
-
- applyEnterAnimationLocked(this);
-
- int i = mChildWindows.size();
- while (i > 0) {
- i--;
- WindowState c = mChildWindows.get(i);
- if (c.mAttachedHidden) {
- c.mAttachedHidden = false;
- if (c.mSurface != null) {
- c.performShowLocked();
- // It hadn't been shown, which means layout not
- // performed on it, so now we want to make sure to
- // do a layout. If called from within the transaction
- // loop, this will cause it to restart with a new
- // layout.
- mLayoutNeeded = true;
- }
- }
- }
-
- if (mAttrs.type != TYPE_APPLICATION_STARTING
- && mAppToken != null) {
- mAppToken.firstWindowDrawn = true;
-
- if (mAppToken.startingData != null) {
- if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
- "Finish starting " + mToken
- + ": first real window is shown, no animation");
- // If this initial window is animating, stop it -- we
- // will do an animation to reveal it from behind the
- // starting window, so there is no need for it to also
- // be doing its own stuff.
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- // Make sure we clean up the animation.
- mAnimating = true;
- }
- mFinishedStarting.add(mAppToken);
- mH.sendEmptyMessage(H.FINISHED_STARTING);
- }
- mAppToken.updateReportedVisibilityLocked();
- }
- }
- return true;
- }
-
- // This must be called while inside a transaction. Returns true if
- // there is more animation to run.
- boolean stepAnimationLocked(long currentTime, int dw, int dh) {
- if (!mDisplayFrozen && mPolicy.isScreenOn()) {
- // We will run animations as long as the display isn't frozen.
-
- if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
- mHasTransformation = true;
- mHasLocalTransformation = true;
- if (!mLocalAnimating) {
- if (DEBUG_ANIM) Slog.v(
- TAG, "Starting animation in " + this +
- " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
- " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
- mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
- mAnimation.setStartTime(currentTime);
- mLocalAnimating = true;
- mAnimating = true;
- }
- mTransformation.clear();
- final boolean more = mAnimation.getTransformation(
- currentTime, mTransformation);
- if (DEBUG_ANIM) Slog.v(
- TAG, "Stepped animation in " + this +
- ": more=" + more + ", xform=" + mTransformation);
- if (more) {
- // we're not done!
- return true;
- }
- if (DEBUG_ANIM) Slog.v(
- TAG, "Finished animation in " + this +
- " @ " + currentTime);
-
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- }
- //WindowManagerService.this.dump();
- }
- mHasLocalTransformation = false;
- if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
- && mAppToken.animation != null) {
- // When our app token is animating, we kind-of pretend like
- // we are as well. Note the mLocalAnimating mAnimationIsEntrance
- // part of this check means that we will only do this if
- // our window is not currently exiting, or it is not
- // locally animating itself. The idea being that one that
- // is exiting and doing a local animation should be removed
- // once that animation is done.
- mAnimating = true;
- mHasTransformation = true;
- mTransformation.clear();
- return false;
- } else if (mHasTransformation) {
- // Little trick to get through the path below to act like
- // we have finished an animation.
- mAnimating = true;
- } else if (isAnimating()) {
- mAnimating = true;
- }
- } else if (mAnimation != null) {
- // If the display is frozen, and there is a pending animation,
- // clear it and make sure we run the cleanup code.
- mAnimating = true;
- mLocalAnimating = true;
- mAnimation.cancel();
- mAnimation = null;
- }
-
- if (!mAnimating && !mLocalAnimating) {
- return false;
- }
-
- if (DEBUG_ANIM) Slog.v(
- TAG, "Animation done in " + this + ": exiting=" + mExiting
- + ", reportedVisible="
- + (mAppToken != null ? mAppToken.reportedVisible : false));
-
- mAnimating = false;
- mLocalAnimating = false;
- if (mAnimation != null) {
- mAnimation.cancel();
- mAnimation = null;
- }
- mAnimLayer = mLayer;
- if (mIsImWindow) {
- mAnimLayer += mInputMethodAnimLayerAdjustment;
- } else if (mIsWallpaper) {
- mAnimLayer += mWallpaperAnimLayerAdjustment;
- }
- if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
- + " anim layer: " + mAnimLayer);
- mHasTransformation = false;
- mHasLocalTransformation = false;
- if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
- if (DEBUG_VISIBILITY) {
- Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
- + mPolicyVisibilityAfterAnim);
- }
- mPolicyVisibility = mPolicyVisibilityAfterAnim;
- if (!mPolicyVisibility) {
- if (mCurrentFocus == this) {
- mFocusMayChange = true;
- }
- // Window is no longer visible -- make sure if we were waiting
- // for it to be displayed before enabling the display, that
- // we allow the display to be enabled now.
- enableScreenIfNeededLocked();
- }
- }
- mTransformation.clear();
- if (mHasDrawn
- && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
- && mAppToken != null
- && mAppToken.firstWindowDrawn
- && mAppToken.startingData != null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
- + mToken + ": first real window done animating");
- mFinishedStarting.add(mAppToken);
- mH.sendEmptyMessage(H.FINISHED_STARTING);
- }
-
- finishExit();
-
- if (mAppToken != null) {
- mAppToken.updateReportedVisibilityLocked();
- }
-
- return false;
- }
-
- void finishExit() {
- if (DEBUG_ANIM) Slog.v(
- TAG, "finishExit in " + this
- + ": exiting=" + mExiting
- + " remove=" + mRemoveOnExit
- + " windowAnimating=" + isWindowAnimating());
-
- final int N = mChildWindows.size();
- for (int i=0; i<N; i++) {
- mChildWindows.get(i).finishExit();
- }
-
- if (!mExiting) {
- return;
- }
-
- if (isWindowAnimating()) {
- return;
- }
-
- if (localLOGV) Slog.v(
- TAG, "Exit animation finished in " + this
- + ": remove=" + mRemoveOnExit);
- if (mSurface != null) {
- mDestroySurface.add(this);
- mDestroying = true;
- if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
- mSurfaceShown = false;
- try {
- mSurface.hide();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error hiding surface in " + this, e);
- }
- mLastHidden = true;
- }
- mExiting = false;
- if (mRemoveOnExit) {
- mPendingRemove.add(this);
- mRemoveOnExit = false;
- }
- }
-
- boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
- if (dsdx < .99999f || dsdx > 1.00001f) return false;
- if (dtdy < .99999f || dtdy > 1.00001f) return false;
- if (dtdx < -.000001f || dtdx > .000001f) return false;
- if (dsdy < -.000001f || dsdy > .000001f) return false;
- return true;
- }
-
- void computeShownFrameLocked() {
- final boolean selfTransformation = mHasLocalTransformation;
- Transformation attachedTransformation =
- (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
- ? mAttachedWindow.mTransformation : null;
- Transformation appTransformation =
- (mAppToken != null && mAppToken.hasTransformation)
- ? mAppToken.transformation : null;
-
- // Wallpapers are animated based on the "real" window they
- // are currently targeting.
- if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
- && mWallpaperTarget != null) {
- if (mWallpaperTarget.mHasLocalTransformation &&
- mWallpaperTarget.mAnimation != null &&
- !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
- attachedTransformation = mWallpaperTarget.mTransformation;
- if (DEBUG_WALLPAPER && attachedTransformation != null) {
- Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
- }
- }
- if (mWallpaperTarget.mAppToken != null &&
- mWallpaperTarget.mAppToken.hasTransformation &&
- mWallpaperTarget.mAppToken.animation != null &&
- !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
- appTransformation = mWallpaperTarget.mAppToken.transformation;
- if (DEBUG_WALLPAPER && appTransformation != null) {
- Slog.v(TAG, "WP target app xform: " + appTransformation);
- }
- }
- }
-
- final boolean screenAnimation = mScreenRotationAnimation != null
- && mScreenRotationAnimation.isAnimating();
- if (selfTransformation || attachedTransformation != null
- || appTransformation != null || screenAnimation) {
- // cache often used attributes locally
- final Rect frame = mFrame;
- final float tmpFloats[] = mTmpFloats;
- final Matrix tmpMatrix = mTmpMatrix;
-
- // Compute the desired transformation.
- tmpMatrix.setTranslate(0, 0);
- if (selfTransformation) {
- tmpMatrix.postConcat(mTransformation.getMatrix());
- }
- tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
- if (attachedTransformation != null) {
- tmpMatrix.postConcat(attachedTransformation.getMatrix());
- }
- if (appTransformation != null) {
- tmpMatrix.postConcat(appTransformation.getMatrix());
- }
- if (screenAnimation) {
- tmpMatrix.postConcat(
- mScreenRotationAnimation.getEnterTransformation().getMatrix());
- }
-
- // "convert" it into SurfaceFlinger's format
- // (a 2x2 matrix + an offset)
- // Here we must not transform the position of the surface
- // since it is already included in the transformation.
- //Slog.i(TAG, "Transform: " + matrix);
-
- mHaveMatrix = true;
- tmpMatrix.getValues(tmpFloats);
- mDsDx = tmpFloats[Matrix.MSCALE_X];
- mDtDx = tmpFloats[Matrix.MSKEW_Y];
- mDsDy = tmpFloats[Matrix.MSKEW_X];
- mDtDy = tmpFloats[Matrix.MSCALE_Y];
- int x = (int)tmpFloats[Matrix.MTRANS_X];
- int y = (int)tmpFloats[Matrix.MTRANS_Y];
- int w = frame.width();
- int h = frame.height();
- mShownFrame.set(x, y, x+w, y+h);
-
- // Now set the alpha... but because our current hardware
- // can't do alpha transformation on a non-opaque surface,
- // turn it off if we are running an animation that is also
- // transforming since it is more important to have that
- // animation be smooth.
- mShownAlpha = mAlpha;
- if (!mLimitedAlphaCompositing
- || (!PixelFormat.formatHasAlpha(mAttrs.format)
- || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
- && x == frame.left && y == frame.top))) {
- //Slog.i(TAG, "Applying alpha transform");
- if (selfTransformation) {
- mShownAlpha *= mTransformation.getAlpha();
- }
- if (attachedTransformation != null) {
- mShownAlpha *= attachedTransformation.getAlpha();
- }
- if (appTransformation != null) {
- mShownAlpha *= appTransformation.getAlpha();
- }
- if (screenAnimation) {
- mShownAlpha *=
- mScreenRotationAnimation.getEnterTransformation().getAlpha();
- }
- } else {
- //Slog.i(TAG, "Not applying alpha transform");
- }
-
- if (localLOGV) Slog.v(
- TAG, "Continuing animation in " + this +
- ": " + mShownFrame +
- ", alpha=" + mTransformation.getAlpha());
- return;
- }
-
- mShownFrame.set(mFrame);
- if (mXOffset != 0 || mYOffset != 0) {
- mShownFrame.offset(mXOffset, mYOffset);
- }
- mShownAlpha = mAlpha;
- mHaveMatrix = false;
- mDsDx = 1;
- mDtDx = 0;
- mDsDy = 0;
- mDtDy = 1;
- }
-
- /**
- * Is this window visible? It is not visible if there is no
- * surface, or we are in the process of running an exit animation
- * that will remove the surface, or its app token has been hidden.
- */
- public boolean isVisibleLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
- && (atoken == null || !atoken.hiddenRequested)
- && !mExiting && !mDestroying;
- }
-
- /**
- * Like {@link #isVisibleLw}, but also counts a window that is currently
- * "hidden" behind the keyguard as visible. This allows us to apply
- * things like window flags that impact the keyguard.
- * XXX I am starting to think we need to have ANOTHER visibility flag
- * for this "hidden behind keyguard" state rather than overloading
- * mPolicyVisibility. Ungh.
- */
- public boolean isVisibleOrBehindKeyguardLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && !mAttachedHidden
- && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
- && !mDrawPending && !mCommitDrawPending
- && !mExiting && !mDestroying;
- }
-
- /**
- * Is this window visible, ignoring its app token? It is not visible
- * if there is no surface, or we are in the process of running an exit animation
- * that will remove the surface.
- */
- public boolean isWinVisibleLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
- && (atoken == null || !atoken.hiddenRequested || atoken.animating)
- && !mExiting && !mDestroying;
- }
-
- /**
- * The same as isVisible(), but follows the current hidden state of
- * the associated app token, not the pending requested hidden state.
- */
- boolean isVisibleNow() {
- return mSurface != null && mPolicyVisibility && !mAttachedHidden
- && !mRootToken.hidden && !mExiting && !mDestroying;
- }
-
- /**
- * Can this window possibly be a drag/drop target? The test here is
- * a combination of the above "visible now" with the check that the
- * Input Manager uses when discarding windows from input consideration.
- */
- boolean isPotentialDragTarget() {
- return isVisibleNow() && (mInputChannel != null) && !mRemoved;
- }
-
- /**
- * Same as isVisible(), but we also count it as visible between the
- * call to IWindowSession.add() and the first relayout().
- */
- boolean isVisibleOrAdding() {
- final AppWindowToken atoken = mAppToken;
- return ((mSurface != null && !mReportDestroySurface)
- || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
- && mPolicyVisibility && !mAttachedHidden
- && (atoken == null || !atoken.hiddenRequested)
- && !mExiting && !mDestroying;
- }
-
- /**
- * Is this window currently on-screen? It is on-screen either if it
- * is visible or it is currently running an animation before no longer
- * being visible.
- */
- boolean isOnScreen() {
- final AppWindowToken atoken = mAppToken;
- if (atoken != null) {
- return mSurface != null && mPolicyVisibility && !mDestroying
- && ((!mAttachedHidden && !atoken.hiddenRequested)
- || mAnimation != null || atoken.animation != null);
- } else {
- return mSurface != null && mPolicyVisibility && !mDestroying
- && (!mAttachedHidden || mAnimation != null);
- }
- }
-
- /**
- * Like isOnScreen(), but we don't return true if the window is part
- * of a transition that has not yet been started.
- */
- boolean isReadyForDisplay() {
- if (mRootToken.waitingToShow &&
- mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
- return false;
- }
- final AppWindowToken atoken = mAppToken;
- final boolean animating = atoken != null
- ? (atoken.animation != null) : false;
- return mSurface != null && mPolicyVisibility && !mDestroying
- && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
- && !mRootToken.hidden)
- || mAnimation != null || animating);
- }
-
- /** Is the window or its container currently animating? */
- boolean isAnimating() {
- final WindowState attached = mAttachedWindow;
- final AppWindowToken atoken = mAppToken;
- return mAnimation != null
- || (attached != null && attached.mAnimation != null)
- || (atoken != null &&
- (atoken.animation != null
- || atoken.inPendingTransaction));
- }
-
- /** Is this window currently animating? */
- boolean isWindowAnimating() {
- return mAnimation != null;
- }
-
- /**
- * Like isOnScreen, but returns false if the surface hasn't yet
- * been drawn.
- */
- public boolean isDisplayedLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && mPolicyVisibility && !mDestroying
- && !mDrawPending && !mCommitDrawPending
- && ((!mAttachedHidden &&
- (atoken == null || !atoken.hiddenRequested))
- || mAnimating);
- }
-
- /**
- * Returns true if the window has a surface that it has drawn a
- * complete UI in to.
- */
- public boolean isDrawnLw() {
- final AppWindowToken atoken = mAppToken;
- return mSurface != null && !mDestroying
- && !mDrawPending && !mCommitDrawPending;
- }
-
- /**
- * Return true if the window is opaque and fully drawn. This indicates
- * it may obscure windows behind it.
- */
- boolean isOpaqueDrawn() {
- return (mAttrs.format == PixelFormat.OPAQUE
- || mAttrs.type == TYPE_WALLPAPER)
- && mSurface != null && mAnimation == null
- && (mAppToken == null || mAppToken.animation == null)
- && !mDrawPending && !mCommitDrawPending;
- }
-
- /**
- * Return whether this window is wanting to have a translation
- * animation applied to it for an in-progress move. (Only makes
- * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
- */
- boolean shouldAnimateMove() {
- return mContentChanged && !mExiting && !mLastHidden && !mDisplayFrozen
- && (mFrame.top != mLastFrame.top
- || mFrame.left != mLastFrame.left)
- && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
- && mPolicy.isScreenOn();
- }
-
- boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
- return
- // only if the application is requesting compatible window
- (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
- // only if it's visible
- mHasDrawn && mViewVisibility == View.VISIBLE &&
- // and only if the application fills the compatible screen
- mFrame.left <= mCompatibleScreenFrame.left &&
- mFrame.top <= mCompatibleScreenFrame.top &&
- mFrame.right >= mCompatibleScreenFrame.right &&
- mFrame.bottom >= mCompatibleScreenFrame.bottom;
- }
-
- boolean isFullscreen(int screenWidth, int screenHeight) {
- return mFrame.left <= 0 && mFrame.top <= 0 &&
- mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
- }
-
- void removeLocked() {
- disposeInputChannel();
-
- if (mAttachedWindow != null) {
- if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
- mAttachedWindow.mChildWindows.remove(this);
- }
- destroySurfaceLocked();
- mSession.windowRemovedLocked();
- try {
- mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
- } catch (RuntimeException e) {
- // Ignore if it has already been removed (usually because
- // we are doing this as part of processing a death note.)
- }
- }
-
- void disposeInputChannel() {
- if (mInputChannel != null) {
- mInputManager.unregisterInputChannel(mInputChannel);
-
- mInputChannel.dispose();
- mInputChannel = null;
- }
- }
-
- private class DeathRecipient implements IBinder.DeathRecipient {
- public void binderDied() {
- try {
- synchronized(mWindowMap) {
- WindowState win = windowForClientLocked(mSession, mClient, false);
- Slog.i(TAG, "WIN DEATH: " + win);
- if (win != null) {
- removeWindowLocked(mSession, win);
- }
- }
- } catch (IllegalArgumentException ex) {
- // This will happen if the window has already been
- // removed.
- }
- }
- }
-
- /** Returns true if this window desires key events. */
- public final boolean canReceiveKeys() {
- return isVisibleOrAdding()
- && (mViewVisibility == View.VISIBLE)
- && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
- }
-
- public boolean hasDrawnLw() {
- return mHasDrawn;
- }
-
- public boolean showLw(boolean doAnimation) {
- return showLw(doAnimation, true);
- }
-
- boolean showLw(boolean doAnimation, boolean requestAnim) {
- if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
- return false;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
- if (doAnimation) {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
- + mPolicyVisibility + " mAnimation=" + mAnimation);
- if (mDisplayFrozen || !mPolicy.isScreenOn()) {
- doAnimation = false;
- } else if (mPolicyVisibility && mAnimation == null) {
- // Check for the case where we are currently visible and
- // not animating; we do not want to do animation at such a
- // point to become visible when we already are.
- doAnimation = false;
- }
- }
- mPolicyVisibility = true;
- mPolicyVisibilityAfterAnim = true;
- if (doAnimation) {
- applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
- }
- if (requestAnim) {
- requestAnimationLocked(0);
- }
- return true;
- }
-
- public boolean hideLw(boolean doAnimation) {
- return hideLw(doAnimation, true);
- }
-
- boolean hideLw(boolean doAnimation, boolean requestAnim) {
- if (doAnimation) {
- if (mDisplayFrozen || !mPolicy.isScreenOn()) {
- doAnimation = false;
- }
- }
- boolean current = doAnimation ? mPolicyVisibilityAfterAnim
- : mPolicyVisibility;
- if (!current) {
- return false;
- }
- if (doAnimation) {
- applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
- if (mAnimation == null) {
- doAnimation = false;
- }
- }
- if (doAnimation) {
- mPolicyVisibilityAfterAnim = false;
- } else {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
- mPolicyVisibilityAfterAnim = false;
- mPolicyVisibility = false;
- // Window is no longer visible -- make sure if we were waiting
- // for it to be displayed before enabling the display, that
- // we allow the display to be enabled now.
- enableScreenIfNeededLocked();
- if (mCurrentFocus == this) {
- mFocusMayChange = true;
- }
- }
- if (requestAnim) {
- requestAnimationLocked(0);
- }
- return true;
- }
-
- public void getTouchableRegion(Region outRegion) {
- final Rect frame = mFrame;
- switch (mTouchableInsets) {
- default:
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
- outRegion.set(frame);
- break;
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
- final Rect inset = mGivenContentInsets;
- outRegion.set(
- frame.left + inset.left, frame.top + inset.top,
- frame.right - inset.right, frame.bottom - inset.bottom);
- break;
- }
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
- final Rect inset = mGivenVisibleInsets;
- outRegion.set(
- frame.left + inset.left, frame.top + inset.top,
- frame.right - inset.right, frame.bottom - inset.bottom);
- break;
- }
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
- final Region givenTouchableRegion = mGivenTouchableRegion;
- outRegion.set(givenTouchableRegion);
- outRegion.translate(frame.left, frame.top);
- break;
- }
- }
- }
-
- void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("mSession="); pw.print(mSession);
- pw.print(" mClient="); pw.println(mClient.asBinder());
- pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
- if (mAttachedWindow != null || mLayoutAttached) {
- pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
- pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
- }
- if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
- pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
- pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
- pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
- pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
- }
- pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
- pw.print(" mSubLayer="); pw.print(mSubLayer);
- pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
- pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
- : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
- pw.print("="); pw.print(mAnimLayer);
- pw.print(" mLastLayer="); pw.println(mLastLayer);
- if (mSurface != null) {
- pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
- pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
- pw.print(" layer="); pw.print(mSurfaceLayer);
- pw.print(" alpha="); pw.print(mSurfaceAlpha);
- pw.print(" rect=("); pw.print(mSurfaceX);
- pw.print(","); pw.print(mSurfaceY);
- pw.print(") "); pw.print(mSurfaceW);
- pw.print(" x "); pw.println(mSurfaceH);
- }
- pw.print(prefix); pw.print("mToken="); pw.println(mToken);
- pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
- if (mAppToken != null) {
- pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
- }
- if (mTargetAppToken != null) {
- pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
- }
- pw.print(prefix); pw.print("mViewVisibility=0x");
- pw.print(Integer.toHexString(mViewVisibility));
- pw.print(" mLastHidden="); pw.print(mLastHidden);
- pw.print(" mHaveFrame="); pw.print(mHaveFrame);
- pw.print(" mObscured="); pw.println(mObscured);
- if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
- pw.print(prefix); pw.print("mPolicyVisibility=");
- pw.print(mPolicyVisibility);
- pw.print(" mPolicyVisibilityAfterAnim=");
- pw.print(mPolicyVisibilityAfterAnim);
- pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
- }
- if (!mRelayoutCalled) {
- pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
- }
- pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
- pw.print(" h="); pw.print(mRequestedHeight);
- pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
- if (mXOffset != 0 || mYOffset != 0) {
- pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
- pw.print(" y="); pw.println(mYOffset);
- }
- pw.print(prefix); pw.print("mGivenContentInsets=");
- mGivenContentInsets.printShortString(pw);
- pw.print(" mGivenVisibleInsets=");
- mGivenVisibleInsets.printShortString(pw);
- pw.println();
- if (mTouchableInsets != 0 || mGivenInsetsPending) {
- pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
- pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
- }
- pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
- pw.print(prefix); pw.print("mShownFrame=");
- mShownFrame.printShortString(pw);
- pw.print(" last="); mLastShownFrame.printShortString(pw);
- pw.println();
- pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
- pw.print(" last="); mLastFrame.printShortString(pw);
- pw.println();
- pw.print(prefix); pw.print("mContainingFrame=");
- mContainingFrame.printShortString(pw);
- pw.print(" mParentFrame=");
- mParentFrame.printShortString(pw);
- pw.print(" mDisplayFrame=");
- mDisplayFrame.printShortString(pw);
- pw.println();
- pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
- pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
- pw.println();
- pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
- pw.print(" last="); mLastContentInsets.printShortString(pw);
- pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
- pw.print(" last="); mLastVisibleInsets.printShortString(pw);
- pw.println();
- if (mAnimating || mLocalAnimating || mAnimationIsEntrance
- || mAnimation != null) {
- pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
- pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
- pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
- pw.print(" mAnimation="); pw.println(mAnimation);
- }
- if (mHasTransformation || mHasLocalTransformation) {
- pw.print(prefix); pw.print("XForm: has=");
- pw.print(mHasTransformation);
- pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
- pw.print(" "); mTransformation.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);
- pw.print(" mLastAlpha="); pw.println(mLastAlpha);
- }
- if (mHaveMatrix) {
- pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx);
- pw.print(" mDtDx="); pw.print(mDtDx);
- pw.print(" mDsDy="); pw.print(mDsDy);
- pw.print(" mDtDy="); pw.println(mDtDy);
- }
- pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
- pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
- pw.print(" mReadyToShow="); pw.print(mReadyToShow);
- pw.print(" mHasDrawn="); pw.println(mHasDrawn);
- if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
- pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
- pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
- pw.print(" mDestroying="); pw.print(mDestroying);
- pw.print(" mRemoved="); pw.println(mRemoved);
- }
- if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
- pw.print(prefix); pw.print("mOrientationChanging=");
- pw.print(mOrientationChanging);
- pw.print(" mAppFreezing="); pw.print(mAppFreezing);
- pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
- }
- if (mHScale != 1 || mVScale != 1) {
- pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
- pw.print(" mVScale="); pw.println(mVScale);
- }
- if (mWallpaperX != -1 || mWallpaperY != -1) {
- pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
- pw.print(" mWallpaperY="); pw.println(mWallpaperY);
- }
- if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
- pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
- pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
- }
- }
-
- String makeInputChannelName() {
- return Integer.toHexString(System.identityHashCode(this))
- + " " + mAttrs.getTitle();
- }
-
- @Override
- public String toString() {
- if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
- || mWasPaused != mToken.paused) {
- mLastTitle = mAttrs.getTitle();
- mWasPaused = mToken.paused;
- mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
- + " " + mLastTitle + " paused=" + mWasPaused + "}";
- }
- return mStringNameCache;
- }
- }
-
- // -------------------------------------------------------------
- // Window Token State
- // -------------------------------------------------------------
-
- class WindowToken {
- // The actual token.
- final IBinder token;
-
- // The type of window this token is for, as per WindowManager.LayoutParams.
- final int windowType;
-
- // Set if this token was explicitly added by a client, so should
- // not be removed when all windows are removed.
- final boolean explicit;
-
- // For printing.
- String stringName;
-
- // If this is an AppWindowToken, this is non-null.
- AppWindowToken appWindowToken;
-
- // All of the windows associated with this token.
- final ArrayList<WindowState> windows = new ArrayList<WindowState>();
-
- // Is key dispatching paused for this token?
- boolean paused = false;
-
- // Should this token's windows be hidden?
- boolean hidden;
-
- // Temporary for finding which tokens no longer have visible windows.
- boolean hasVisible;
-
- // Set to true when this token is in a pending transaction where it
- // will be shown.
- boolean waitingToShow;
-
- // Set to true when this token is in a pending transaction where it
- // will be hidden.
- boolean waitingToHide;
-
- // Set to true when this token is in a pending transaction where its
- // windows will be put to the bottom of the list.
- boolean sendingToBottom;
-
- // Set to true when this token is in a pending transaction where its
- // windows will be put to the top of the list.
- boolean sendingToTop;
-
- WindowToken(IBinder _token, int type, boolean _explicit) {
- token = _token;
- windowType = type;
- explicit = _explicit;
- }
-
- void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("token="); pw.println(token);
- pw.print(prefix); pw.print("windows="); pw.println(windows);
- pw.print(prefix); pw.print("windowType="); pw.print(windowType);
- pw.print(" hidden="); pw.print(hidden);
- pw.print(" hasVisible="); pw.println(hasVisible);
- if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
- pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
- pw.print(" waitingToHide="); pw.print(waitingToHide);
- pw.print(" sendingToBottom="); pw.print(sendingToBottom);
- pw.print(" sendingToTop="); pw.println(sendingToTop);
- }
- }
-
- @Override
- public String toString() {
- if (stringName == null) {
- StringBuilder sb = new StringBuilder();
- sb.append("WindowToken{");
- sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(" token="); sb.append(token); sb.append('}');
- stringName = sb.toString();
- }
- return stringName;
- }
- };
-
- class AppWindowToken extends WindowToken {
- // Non-null only for application tokens.
- final IApplicationToken appToken;
-
- // All of the windows and child windows that are included in this
- // application token. Note this list is NOT sorted!
- final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
-
- int groupId = -1;
- boolean appFullscreen;
- int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-
- // The input dispatching timeout for this application token in nanoseconds.
- long inputDispatchingTimeoutNanos;
-
- // These are used for determining when all windows associated with
- // an activity have been drawn, so they can be made visible together
- // at the same time.
- int lastTransactionSequence = mTransactionSequence-1;
- int numInterestingWindows;
- int numDrawnWindows;
- boolean inPendingTransaction;
- boolean allDrawn;
-
- // Is this token going to be hidden in a little while? If so, it
- // won't be taken into account for setting the screen orientation.
- boolean willBeHidden;
-
- // Is this window's surface needed? This is almost like hidden, except
- // it will sometimes be true a little earlier: when the token has
- // been shown, but is still waiting for its app transition to execute
- // before making its windows shown.
- boolean hiddenRequested;
-
- // Have we told the window clients to hide themselves?
- boolean clientHidden;
-
- // Last visibility state we reported to the app token.
- boolean reportedVisible;
-
- // Set to true when the token has been removed from the window mgr.
- boolean removed;
-
- // Have we been asked to have this token keep the screen frozen?
- boolean freezingScreen;
-
- boolean animating;
- Animation animation;
- boolean hasTransformation;
- final Transformation transformation = new Transformation();
-
- // Offset to the window of all layers in the token, for use by
- // AppWindowToken animations.
- int animLayerAdjustment;
-
- // Information about an application starting window if displayed.
- StartingData startingData;
- WindowState startingWindow;
- View startingView;
- boolean startingDisplayed;
- boolean startingMoved;
- boolean firstWindowDrawn;
-
- // Input application handle used by the input dispatcher.
- InputApplicationHandle mInputApplicationHandle;
-
- AppWindowToken(IApplicationToken _token) {
- super(_token.asBinder(),
- WindowManager.LayoutParams.TYPE_APPLICATION, true);
- appWindowToken = this;
- appToken = _token;
- mInputApplicationHandle = new InputApplicationHandle(this);
- }
-
- public void setAnimation(Animation anim) {
- if (localLOGV) Slog.v(
- TAG, "Setting animation in " + this + ": " + anim);
- animation = anim;
- animating = false;
- anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(mTransitionAnimationScale);
- int zorder = anim.getZAdjustment();
- int adj = 0;
- if (zorder == Animation.ZORDER_TOP) {
- adj = TYPE_LAYER_OFFSET;
- } else if (zorder == Animation.ZORDER_BOTTOM) {
- adj = -TYPE_LAYER_OFFSET;
- }
-
- if (animLayerAdjustment != adj) {
- animLayerAdjustment = adj;
- updateLayers();
- }
- }
-
- public void setDummyAnimation() {
- if (animation == null) {
- if (localLOGV) Slog.v(
- TAG, "Setting dummy animation in " + this);
- animation = sDummyAnimation;
- }
- }
-
- public void clearAnimation() {
- if (animation != null) {
- animation = null;
- animating = true;
- }
- }
-
- void updateLayers() {
- final int N = allAppWindows.size();
- final int adj = animLayerAdjustment;
- for (int i=0; i<N; i++) {
- WindowState w = allAppWindows.get(i);
- w.mAnimLayer = w.mLayer + adj;
- if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
- + w.mAnimLayer);
- if (w == mInputMethodTarget && !mInputMethodTargetWaitingAnim) {
- setInputMethodAnimLayerAdjustment(adj);
- }
- if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
- setWallpaperAnimLayerAdjustmentLocked(adj);
- }
- }
- }
-
- void sendAppVisibilityToClients() {
- final int N = allAppWindows.size();
- for (int i=0; i<N; i++) {
- WindowState win = allAppWindows.get(i);
- if (win == startingWindow && clientHidden) {
- // Don't hide the starting window.
- continue;
- }
- try {
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "Setting visibility of " + win + ": " + (!clientHidden));
- win.mClient.dispatchAppVisibility(!clientHidden);
- } catch (RemoteException e) {
- }
- }
- }
-
- void showAllWindowsLocked() {
- final int NW = allAppWindows.size();
- for (int i=0; i<NW; i++) {
- WindowState w = allAppWindows.get(i);
- if (DEBUG_VISIBILITY) Slog.v(TAG,
- "performing show on: " + w);
- w.performShowLocked();
- }
- }
-
- // This must be called while inside a transaction.
- boolean stepAnimationLocked(long currentTime, int dw, int dh) {
- if (!mDisplayFrozen && mPolicy.isScreenOn()) {
- // We will run animations as long as the display isn't frozen.
-
- if (animation == sDummyAnimation) {
- // This guy is going to animate, but not yet. For now count
- // it as not animating for purposes of scheduling transactions;
- // when it is really time to animate, this will be set to
- // a real animation and the next call will execute normally.
- return false;
- }
-
- if ((allDrawn || animating || startingDisplayed) && animation != null) {
- if (!animating) {
- if (DEBUG_ANIM) Slog.v(
- TAG, "Starting animation in " + this +
- " @ " + currentTime + ": dw=" + dw + " dh=" + dh
- + " scale=" + mTransitionAnimationScale
- + " allDrawn=" + allDrawn + " animating=" + animating);
- animation.initialize(dw, dh, dw, dh);
- animation.setStartTime(currentTime);
- animating = true;
- }
- transformation.clear();
- final boolean more = animation.getTransformation(
- currentTime, transformation);
- if (DEBUG_ANIM) Slog.v(
- TAG, "Stepped animation in " + this +
- ": more=" + more + ", xform=" + transformation);
- if (more) {
- // we're done!
- hasTransformation = true;
- return true;
- }
- if (DEBUG_ANIM) Slog.v(
- TAG, "Finished animation in " + this +
- " @ " + currentTime);
- animation = null;
- }
- } else if (animation != null) {
- // If the display is frozen, and there is a pending animation,
- // clear it and make sure we run the cleanup code.
- animating = true;
- animation = null;
- }
-
- hasTransformation = false;
-
- if (!animating) {
- return false;
- }
-
- clearAnimation();
- animating = false;
- if (animLayerAdjustment != 0) {
- animLayerAdjustment = 0;
- updateLayers();
- }
- if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
- moveInputMethodWindowsIfNeededLocked(true);
- }
-
- if (DEBUG_ANIM) Slog.v(
- TAG, "Animation done in " + this
- + ": reportedVisible=" + reportedVisible);
-
- transformation.clear();
-
- final int N = windows.size();
- for (int i=0; i<N; i++) {
- windows.get(i).finishExit();
- }
- updateReportedVisibilityLocked();
-
- return false;
- }
-
- void updateReportedVisibilityLocked() {
- if (appToken == null) {
- return;
- }
-
- int numInteresting = 0;
- int numVisible = 0;
- boolean nowGone = true;
-
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
- final int N = allAppWindows.size();
- for (int i=0; i<N; i++) {
- WindowState win = allAppWindows.get(i);
- if (win == startingWindow || win.mAppFreezing
- || win.mViewVisibility != View.VISIBLE
- || win.mAttrs.type == TYPE_APPLICATION_STARTING
- || win.mDestroying) {
- continue;
- }
- if (DEBUG_VISIBILITY) {
- Slog.v(TAG, "Win " + win + ": isDrawn="
- + win.isDrawnLw()
- + ", isAnimating=" + win.isAnimating());
- if (!win.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s=" + win.mSurface
- + " pv=" + win.mPolicyVisibility
- + " dp=" + win.mDrawPending
- + " cdp=" + win.mCommitDrawPending
- + " ah=" + win.mAttachedHidden
- + " th="
- + (win.mAppToken != null
- ? win.mAppToken.hiddenRequested : false)
- + " a=" + win.mAnimating);
- }
- }
- numInteresting++;
- if (win.isDrawnLw()) {
- if (!win.isAnimating()) {
- numVisible++;
- }
- nowGone = false;
- } else if (win.isAnimating()) {
- nowGone = false;
- }
- }
-
- boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
- if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
- + numInteresting + " visible=" + numVisible);
- if (nowVisible != reportedVisible) {
- if (DEBUG_VISIBILITY) Slog.v(
- TAG, "Visibility changed in " + this
- + ": vis=" + nowVisible);
- reportedVisible = nowVisible;
- Message m = mH.obtainMessage(
- H.REPORT_APPLICATION_TOKEN_WINDOWS,
- nowVisible ? 1 : 0,
- nowGone ? 1 : 0,
- this);
- mH.sendMessage(m);
- }
- }
-
- WindowState findMainWindow() {
- int j = windows.size();
- while (j > 0) {
- j--;
- WindowState win = windows.get(j);
- if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
- || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
- return win;
- }
- }
- return null;
- }
-
- void dump(PrintWriter pw, String prefix) {
- super.dump(pw, prefix);
- if (appToken != null) {
- pw.print(prefix); pw.println("app=true");
- }
- 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(" requestedOrientation="); pw.println(requestedOrientation);
- pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
- pw.print(" clientHidden="); pw.print(clientHidden);
- pw.print(" willBeHidden="); pw.print(willBeHidden);
- pw.print(" reportedVisible="); pw.println(reportedVisible);
- if (paused || freezingScreen) {
- pw.print(prefix); pw.print("paused="); pw.print(paused);
- pw.print(" freezingScreen="); pw.println(freezingScreen);
- }
- if (numInterestingWindows != 0 || numDrawnWindows != 0
- || inPendingTransaction || allDrawn) {
- pw.print(prefix); pw.print("numInterestingWindows=");
- pw.print(numInterestingWindows);
- pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
- pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
- pw.print(" allDrawn="); pw.println(allDrawn);
- }
- if (animating || animation != null) {
- pw.print(prefix); pw.print("animating="); pw.print(animating);
- pw.print(" animation="); pw.println(animation);
- }
- if (hasTransformation) {
- pw.print(prefix); pw.print("XForm: ");
- transformation.printShortString(pw);
- pw.println();
- }
- if (animLayerAdjustment != 0) {
- pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
- }
- if (startingData != null || removed || firstWindowDrawn) {
- pw.print(prefix); pw.print("startingData="); pw.print(startingData);
- pw.print(" removed="); pw.print(removed);
- pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
- }
- if (startingWindow != null || startingView != null
- || startingDisplayed || startingMoved) {
- pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
- pw.print(" startingView="); pw.print(startingView);
- pw.print(" startingDisplayed="); pw.print(startingDisplayed);
- pw.print(" startingMoved"); pw.println(startingMoved);
- }
- }
-
- @Override
- public String toString() {
- if (stringName == null) {
- StringBuilder sb = new StringBuilder();
- sb.append("AppWindowToken{");
- sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(" token="); sb.append(token); sb.append('}');
- stringName = sb.toString();
- }
- return stringName;
- }
- }
-
- // -------------------------------------------------------------
- // DummyAnimation
- // -------------------------------------------------------------
-
// This is an animation that does nothing: it just immediately finishes
// itself every time it is called. It is used as a stub animation in cases
// where we want to synchronize multiple things that may be animating.
@@ -8919,26 +5826,7 @@
// Async Handler
// -------------------------------------------------------------
- static final class StartingData {
- final String pkg;
- final int theme;
- final CharSequence nonLocalizedLabel;
- final int labelRes;
- final int icon;
- final int windowFlags;
-
- StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
- int _labelRes, int _icon, int _windowFlags) {
- pkg = _pkg;
- theme = _theme;
- nonLocalizedLabel = _nonLocalizedLabel;
- labelRes = _labelRes;
- icon = _icon;
- windowFlags = _windowFlags;
- }
- }
-
- private final class H extends Handler {
+ final class H extends Handler {
public static final int REPORT_FOCUS_CHANGE = 2;
public static final int REPORT_LOSING_FOCUS = 3;
public static final int ANIMATE = 4;
@@ -9348,7 +6236,7 @@
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
- Session session = new Session(client, inputContext);
+ Session session = new Session(this, client, inputContext);
return session;
}
@@ -11482,148 +8370,6 @@
return val;
}
- static class Watermark {
- final String[] mTokens;
- final String mText;
- final Paint mTextPaint;
- final int mTextWidth;
- final int mTextHeight;
- final int mTextAscent;
- final int mTextDescent;
- final int mDeltaX;
- final int mDeltaY;
-
- Surface mSurface;
- int mLastDW;
- int mLastDH;
- boolean mDrawNeeded;
-
- Watermark(Display display, SurfaceSession session, String[] tokens) {
- final DisplayMetrics dm = new DisplayMetrics();
- display.getMetrics(dm);
-
- if (false) {
- Log.i(TAG, "*********************** WATERMARK");
- for (int i=0; i<tokens.length; i++) {
- Log.i(TAG, " TOKEN #" + i + ": " + tokens[i]);
- }
- }
-
- mTokens = tokens;
-
- StringBuilder builder = new StringBuilder(32);
- int len = mTokens[0].length();
- len = len & ~1;
- for (int i=0; i<len; i+=2) {
- int c1 = mTokens[0].charAt(i);
- int c2 = mTokens[0].charAt(i+1);
- if (c1 >= 'a' && c1 <= 'f') c1 = c1 - 'a' + 10;
- else if (c1 >= 'A' && c1 <= 'F') c1 = c1 - 'A' + 10;
- else c1 -= '0';
- if (c2 >= 'a' && c2 <= 'f') c2 = c2 - 'a' + 10;
- else if (c2 >= 'A' && c2 <= 'F') c2 = c2 - 'A' + 10;
- else c2 -= '0';
- builder.append((char)(255-((c1*16)+c2)));
- }
- mText = builder.toString();
- if (false) {
- Log.i(TAG, "Final text: " + mText);
- }
-
- int fontSize = getPropertyInt(tokens, 1,
- TypedValue.COMPLEX_UNIT_DIP, 20, dm);
-
- mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mTextPaint.setTextSize(fontSize);
- mTextPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD));
-
- FontMetricsInt fm = mTextPaint.getFontMetricsInt();
- mTextWidth = (int)mTextPaint.measureText(mText);
- mTextAscent = fm.ascent;
- mTextDescent = fm.descent;
- mTextHeight = fm.descent - fm.ascent;
-
- mDeltaX = getPropertyInt(tokens, 2,
- TypedValue.COMPLEX_UNIT_PX, mTextWidth*2, dm);
- mDeltaY = getPropertyInt(tokens, 3,
- TypedValue.COMPLEX_UNIT_PX, mTextHeight*3, dm);
- int shadowColor = getPropertyInt(tokens, 4,
- TypedValue.COMPLEX_UNIT_PX, 0xb0000000, dm);
- int color = getPropertyInt(tokens, 5,
- TypedValue.COMPLEX_UNIT_PX, 0x60ffffff, dm);
- int shadowRadius = getPropertyInt(tokens, 6,
- TypedValue.COMPLEX_UNIT_PX, 7, dm);
- int shadowDx = getPropertyInt(tokens, 8,
- TypedValue.COMPLEX_UNIT_PX, 0, dm);
- int shadowDy = getPropertyInt(tokens, 9,
- TypedValue.COMPLEX_UNIT_PX, 0, dm);
-
- mTextPaint.setColor(color);
- mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
-
- try {
- mSurface = new Surface(session, 0,
- "WatermarkSurface", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
- mSurface.setLayer(TYPE_LAYER_MULTIPLIER*100);
- mSurface.setPosition(0, 0);
- mSurface.show();
- } catch (OutOfResourcesException e) {
- }
- }
-
- void positionSurface(int dw, int dh) {
- if (mLastDW != dw || mLastDH != dh) {
- mLastDW = dw;
- mLastDH = dh;
- mSurface.setSize(dw, dh);
- mDrawNeeded = true;
- }
- }
-
- void drawIfNeeded() {
- if (mDrawNeeded) {
- final int dw = mLastDW;
- final int dh = mLastDH;
-
- mDrawNeeded = false;
- Rect dirty = new Rect(0, 0, dw, dh);
- Canvas c = null;
- try {
- c = mSurface.lockCanvas(dirty);
- } catch (IllegalArgumentException e) {
- } catch (OutOfResourcesException e) {
- }
- if (c != null) {
- c.drawColor(0, PorterDuff.Mode.CLEAR);
-
- int deltaX = mDeltaX;
- int deltaY = mDeltaY;
-
- // deltaX shouldn't be close to a round fraction of our
- // x step, or else things will line up too much.
- int div = (dw+mTextWidth)/deltaX;
- int rem = (dw+mTextWidth) - (div*deltaX);
- int qdelta = deltaX/4;
- if (rem < qdelta || rem > (deltaX-qdelta)) {
- deltaX += deltaX/3;
- }
-
- int y = -mTextHeight;
- int x = -mTextWidth;
- while (y < (dh+mTextHeight)) {
- c.drawText(mText, x, y, mTextPaint);
- x += deltaX;
- if (x >= dw) {
- x -= (dw+mTextWidth);
- y += deltaY;
- }
- }
- mSurface.unlockCanvasAndPost(c);
- }
- }
- }
- }
-
void createWatermark() {
if (mWatermark != null) {
return;
@@ -11905,190 +8651,6 @@
synchronized (mKeyguardTokenWatcher) { }
}
- /**
- * DimAnimator class that controls the dim animation. This holds the surface and
- * all state used for dim animation.
- */
- private static class DimAnimator {
- Surface mDimSurface;
- boolean mDimShown = false;
- float mDimCurrentAlpha;
- float mDimTargetAlpha;
- float mDimDeltaPerMs;
- long mLastDimAnimTime;
-
- int mLastDimWidth, mLastDimHeight;
-
- DimAnimator (SurfaceSession session) {
- if (mDimSurface == null) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
- + mDimSurface + ": CREATE");
- try {
- mDimSurface = new Surface(session, 0,
- "DimSurface",
- -1, 16, 16, PixelFormat.OPAQUE,
- Surface.FX_SURFACE_DIM);
- mDimSurface.setAlpha(0.0f);
- } catch (Exception e) {
- Slog.e(TAG, "Exception creating Dim surface", e);
- }
- }
- }
-
- /**
- * Show the dim surface.
- */
- void show(int dw, int dh) {
- if (!mDimShown) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
- dw + "x" + dh + ")");
- mDimShown = true;
- try {
- mLastDimWidth = dw;
- mLastDimHeight = dh;
- mDimSurface.setPosition(0, 0);
- mDimSurface.setSize(dw, dh);
- mDimSurface.show();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure showing dim surface", e);
- }
- } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
- mLastDimWidth = dw;
- mLastDimHeight = dh;
- mDimSurface.setSize(dw, dh);
- }
- }
-
- /**
- * Set's the dim surface's layer and update dim parameters that will be used in
- * {@link updateSurface} after all windows are examined.
- */
- void updateParameters(Resources res, WindowState w, long currentTime) {
- mDimSurface.setLayer(w.mAnimLayer-1);
-
- final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
- + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
- if (mDimTargetAlpha != target) {
- // If the desired dim level has changed, then
- // start an animation to it.
- mLastDimAnimTime = currentTime;
- long duration = (w.mAnimating && w.mAnimation != null)
- ? w.mAnimation.computeDurationHint()
- : DEFAULT_DIM_DURATION;
- if (target > mDimTargetAlpha) {
- TypedValue tv = new TypedValue();
- res.getValue(com.android.internal.R.fraction.config_dimBehindFadeDuration,
- tv, true);
- if (tv.type == TypedValue.TYPE_FRACTION) {
- duration = (long)tv.getFraction((float)duration, (float)duration);
- } else if (tv.type >= TypedValue.TYPE_FIRST_INT
- && tv.type <= TypedValue.TYPE_LAST_INT) {
- duration = tv.data;
- }
- }
- if (duration < 1) {
- // Don't divide by zero
- duration = 1;
- }
- mDimTargetAlpha = target;
- mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
- }
- }
-
- /**
- * Updating the surface's alpha. Returns true if the animation continues, or returns
- * false when the animation is finished and the dim surface is hidden.
- */
- boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
- if (!dimming) {
- if (mDimTargetAlpha != 0) {
- mLastDimAnimTime = currentTime;
- mDimTargetAlpha = 0;
- mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
- }
- }
-
- boolean animating = false;
- if (mLastDimAnimTime != 0) {
- mDimCurrentAlpha += mDimDeltaPerMs
- * (currentTime-mLastDimAnimTime);
- boolean more = true;
- if (displayFrozen) {
- // If the display is frozen, there is no reason to animate.
- more = false;
- } else if (mDimDeltaPerMs > 0) {
- if (mDimCurrentAlpha > mDimTargetAlpha) {
- more = false;
- }
- } else if (mDimDeltaPerMs < 0) {
- if (mDimCurrentAlpha < mDimTargetAlpha) {
- more = false;
- }
- } else {
- more = false;
- }
-
- // Do we need to continue animating?
- if (more) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
- + mDimSurface + ": alpha=" + mDimCurrentAlpha);
- mLastDimAnimTime = currentTime;
- mDimSurface.setAlpha(mDimCurrentAlpha);
- animating = true;
- } else {
- mDimCurrentAlpha = mDimTargetAlpha;
- mLastDimAnimTime = 0;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
- + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
- mDimSurface.setAlpha(mDimCurrentAlpha);
- if (!dimming) {
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
- + ": HIDE");
- try {
- mDimSurface.hide();
- } catch (RuntimeException e) {
- Slog.w(TAG, "Illegal argument exception hiding dim surface");
- }
- mDimShown = false;
- }
- }
- }
- return animating;
- }
-
- public void printTo(PrintWriter pw) {
- pw.print(" mDimShown="); pw.print(mDimShown);
- pw.print(" current="); pw.print(mDimCurrentAlpha);
- pw.print(" target="); pw.print(mDimTargetAlpha);
- pw.print(" delta="); pw.print(mDimDeltaPerMs);
- pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
- }
- }
-
- /**
- * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
- * This is used for opening/closing transition for apps in compatible mode.
- */
- private static class FadeInOutAnimation extends Animation {
- boolean mFadeIn;
-
- public FadeInOutAnimation(boolean fadeIn) {
- setInterpolator(new AccelerateInterpolator());
- setDuration(DEFAULT_FADE_IN_OUT_DURATION);
- mFadeIn = fadeIn;
- }
-
- @Override
- protected void applyTransformation(float interpolatedTime, Transformation t) {
- float x = interpolatedTime;
- if (!mFadeIn) {
- x = 1.0f - x; // reverse the interpolation for fade out
- }
- t.setAlpha(x);
- }
- }
-
public interface OnHardKeyboardStatusChangeListener {
public void onHardKeyboardStatusChange(boolean available, boolean enabled);
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
new file mode 100644
index 0000000..d0eec89
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -0,0 +1,1623 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+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 com.android.server.wm.WindowManagerService.H;
+
+import android.content.res.Configuration;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.InputChannel;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.WindowManager.LayoutParams;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * A window in the window manager.
+ */
+final class WindowState implements WindowManagerPolicy.WindowState {
+ final WindowManagerService mService;
+ final Session mSession;
+ final IWindow mClient;
+ WindowToken mToken;
+ WindowToken mRootToken;
+ AppWindowToken mAppToken;
+ AppWindowToken mTargetAppToken;
+ final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
+ final DeathRecipient mDeathRecipient;
+ final WindowState mAttachedWindow;
+ final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
+ final int mBaseLayer;
+ final int mSubLayer;
+ final boolean mLayoutAttached;
+ final boolean mIsImWindow;
+ final boolean mIsWallpaper;
+ final boolean mIsFloatingLayer;
+ int mViewVisibility;
+ boolean mPolicyVisibility = true;
+ boolean mPolicyVisibilityAfterAnim = true;
+ boolean mAppFreezing;
+ Surface mSurface;
+ boolean mReportDestroySurface;
+ boolean mSurfacePendingDestroy;
+ boolean mAttachedHidden; // is our parent window hidden?
+ boolean mLastHidden; // was this window last hidden?
+ boolean mWallpaperVisible; // for wallpaper, what was last vis report?
+ int mRequestedWidth;
+ int mRequestedHeight;
+ int mLastRequestedWidth;
+ int mLastRequestedHeight;
+ int mLayer;
+ int mAnimLayer;
+ int mLastLayer;
+ boolean mHaveFrame;
+ boolean mObscured;
+ boolean mTurnOnScreen;
+
+ int mLayoutSeq = -1;
+
+ Configuration mConfiguration = null;
+
+ // Actual frame shown on-screen (may be modified by animation)
+ final Rect mShownFrame = new Rect();
+ final Rect mLastShownFrame = new Rect();
+
+ /**
+ * Set when we have changed the size of the surface, to know that
+ * we must tell them application to resize (and thus redraw itself).
+ */
+ boolean mSurfaceResized;
+
+ /**
+ * Insets that determine the actually visible area
+ */
+ final Rect mVisibleInsets = new Rect();
+ final Rect mLastVisibleInsets = new Rect();
+ boolean mVisibleInsetsChanged;
+
+ /**
+ * Insets that are covered by system windows
+ */
+ final Rect mContentInsets = new Rect();
+ final Rect mLastContentInsets = new Rect();
+ boolean mContentInsetsChanged;
+
+ /**
+ * Set to true if we are waiting for this window to receive its
+ * given internal insets before laying out other windows based on it.
+ */
+ boolean mGivenInsetsPending;
+
+ /**
+ * These are the content insets that were given during layout for
+ * this window, to be applied to windows behind it.
+ */
+ final Rect mGivenContentInsets = new Rect();
+
+ /**
+ * These are the visible insets that were given during layout for
+ * this window, to be applied to windows behind it.
+ */
+ final Rect mGivenVisibleInsets = new Rect();
+
+ /**
+ * This is the given touchable area relative to the window frame, or null if none.
+ */
+ final Region mGivenTouchableRegion = new Region();
+
+ /**
+ * Flag indicating whether the touchable region should be adjusted by
+ * the visible insets; if false the area outside the visible insets is
+ * NOT touchable, so we must use those to adjust the frame during hit
+ * tests.
+ */
+ int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
+
+ // Current transformation being applied.
+ boolean mHaveMatrix;
+ float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
+ float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
+ float mHScale=1, mVScale=1;
+ float mLastHScale=1, mLastVScale=1;
+ final Matrix mTmpMatrix = new Matrix();
+
+ // "Real" frame that the application sees.
+ final Rect mFrame = new Rect();
+ final Rect mLastFrame = new Rect();
+
+ final Rect mContainingFrame = new Rect();
+ final Rect mDisplayFrame = new Rect();
+ final Rect mContentFrame = new Rect();
+ final Rect mParentFrame = new Rect();
+ final Rect mVisibleFrame = new Rect();
+
+ boolean mContentChanged;
+
+ float mShownAlpha = 1;
+ float mAlpha = 1;
+ float mLastAlpha = 1;
+
+ // Set to true if, when the window gets displayed, it should perform
+ // an enter animation.
+ boolean mEnterAnimationPending;
+
+ // Currently running animation.
+ boolean mAnimating;
+ boolean mLocalAnimating;
+ Animation mAnimation;
+ boolean mAnimationIsEntrance;
+ boolean mHasTransformation;
+ boolean mHasLocalTransformation;
+ final Transformation mTransformation = new Transformation();
+
+ // If a window showing a wallpaper: the requested offset for the
+ // wallpaper; if a wallpaper window: the currently applied offset.
+ float mWallpaperX = -1;
+ float mWallpaperY = -1;
+
+ // If a window showing a wallpaper: what fraction of the offset
+ // range corresponds to a full virtual screen.
+ float mWallpaperXStep = -1;
+ float mWallpaperYStep = -1;
+
+ // Wallpaper windows: pixels offset based on above variables.
+ int mXOffset;
+ int mYOffset;
+
+ // This is set after IWindowSession.relayout() has been called at
+ // least once for the window. It allows us to detect the situation
+ // where we don't yet have a surface, but should have one soon, so
+ // we can give the window focus before waiting for the relayout.
+ boolean mRelayoutCalled;
+
+ // This is set after the Surface has been created but before the
+ // window has been drawn. During this time the surface is hidden.
+ boolean mDrawPending;
+
+ // This is set after the window has finished drawing for the first
+ // time but before its surface is shown. The surface will be
+ // displayed when the next layout is run.
+ boolean mCommitDrawPending;
+
+ // This is set during the time after the window's drawing has been
+ // committed, and before its surface is actually shown. It is used
+ // to delay showing the surface until all windows in a token are ready
+ // to be shown.
+ boolean mReadyToShow;
+
+ // Set when the window has been shown in the screen the first time.
+ boolean mHasDrawn;
+
+ // Currently running an exit animation?
+ boolean mExiting;
+
+ // Currently on the mDestroySurface list?
+ boolean mDestroying;
+
+ // Completely remove from window manager after exit animation?
+ boolean mRemoveOnExit;
+
+ // Set when the orientation is changing and this window has not yet
+ // been updated for the new orientation.
+ boolean mOrientationChanging;
+
+ // Is this window now (or just being) removed?
+ boolean mRemoved;
+
+ // Temp for keeping track of windows that have been removed when
+ // rebuilding window list.
+ boolean mRebuilding;
+
+ // For debugging, this is the last information given to the surface flinger.
+ boolean mSurfaceShown;
+ int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
+ int mSurfaceLayer;
+ float mSurfaceAlpha;
+
+ // Input channel and input window handle used by the input dispatcher.
+ InputWindowHandle mInputWindowHandle;
+ InputChannel mInputChannel;
+
+ // Used to improve performance of toString()
+ String mStringNameCache;
+ CharSequence mLastTitle;
+ boolean mWasPaused;
+
+ WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
+ WindowState attachedWindow, WindowManager.LayoutParams a,
+ int viewVisibility) {
+ mService = service;
+ mSession = s;
+ mClient = c;
+ mToken = token;
+ mAttrs.copyFrom(a);
+ mViewVisibility = viewVisibility;
+ DeathRecipient deathRecipient = new DeathRecipient();
+ mAlpha = a.alpha;
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+ + " token=" + token + " (" + mAttrs.token + ")");
+ try {
+ c.asBinder().linkToDeath(deathRecipient, 0);
+ } catch (RemoteException e) {
+ mDeathRecipient = null;
+ mAttachedWindow = null;
+ mLayoutAttached = false;
+ mIsImWindow = false;
+ mIsWallpaper = false;
+ mIsFloatingLayer = false;
+ mBaseLayer = 0;
+ mSubLayer = 0;
+ return;
+ }
+ mDeathRecipient = deathRecipient;
+
+ if ((mAttrs.type >= FIRST_SUB_WINDOW &&
+ mAttrs.type <= LAST_SUB_WINDOW)) {
+ // The multiplier here is to reserve space for multiple
+ // windows in the same type layer.
+ mBaseLayer = mService.mPolicy.windowTypeToLayerLw(
+ attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ mSubLayer = mService.mPolicy.subWindowTypeToLayerLw(a.type);
+ mAttachedWindow = attachedWindow;
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
+ mAttachedWindow.mChildWindows.add(this);
+ mLayoutAttached = mAttrs.type !=
+ WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+ mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
+ || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
+ mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
+ mIsFloatingLayer = mIsImWindow || mIsWallpaper;
+ } else {
+ // The multiplier here is to reserve space for multiple
+ // windows in the same type layer.
+ mBaseLayer = mService.mPolicy.windowTypeToLayerLw(a.type)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ mSubLayer = 0;
+ mAttachedWindow = null;
+ mLayoutAttached = false;
+ mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
+ || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
+ mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
+ mIsFloatingLayer = mIsImWindow || mIsWallpaper;
+ }
+
+ WindowState appWin = this;
+ while (appWin.mAttachedWindow != null) {
+ appWin = mAttachedWindow;
+ }
+ WindowToken appToken = appWin.mToken;
+ while (appToken.appWindowToken == null) {
+ WindowToken parent = mService.mTokenMap.get(appToken.token);
+ if (parent == null || appToken == parent) {
+ break;
+ }
+ appToken = parent;
+ }
+ mRootToken = appToken;
+ mAppToken = appToken.appWindowToken;
+
+ mSurface = null;
+ mRequestedWidth = 0;
+ mRequestedHeight = 0;
+ mLastRequestedWidth = 0;
+ mLastRequestedHeight = 0;
+ mXOffset = 0;
+ mYOffset = 0;
+ mLayer = 0;
+ mAnimLayer = 0;
+ mLastLayer = 0;
+ mInputWindowHandle = new InputWindowHandle(
+ mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
+ }
+
+ void attach() {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
+ + ", list=" + mToken.windows);
+ mSession.windowAddedLocked();
+ }
+
+ public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
+ mHaveFrame = true;
+
+ final Rect container = mContainingFrame;
+ container.set(pf);
+
+ final Rect display = mDisplayFrame;
+ display.set(df);
+
+ if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+ container.intersect(mService.mCompatibleScreenFrame);
+ if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
+ display.intersect(mService.mCompatibleScreenFrame);
+ }
+ }
+
+ final int pw = container.right - container.left;
+ final int ph = container.bottom - container.top;
+
+ int w,h;
+ if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
+ w = mAttrs.width < 0 ? pw : mAttrs.width;
+ h = mAttrs.height< 0 ? ph : mAttrs.height;
+ } else {
+ w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
+ h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
+ }
+
+ if (!mParentFrame.equals(pf)) {
+ //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
+ // + " to " + pf);
+ mParentFrame.set(pf);
+ mContentChanged = true;
+ }
+
+ final Rect content = mContentFrame;
+ content.set(cf);
+
+ final Rect visible = mVisibleFrame;
+ visible.set(vf);
+
+ final Rect frame = mFrame;
+ final int fw = frame.width();
+ final int fh = frame.height();
+
+ //System.out.println("In: w=" + w + " h=" + h + " container=" +
+ // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
+
+ Gravity.apply(mAttrs.gravity, w, h, container,
+ (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
+ (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
+
+ //System.out.println("Out: " + mFrame);
+
+ // Now make sure the window fits in the overall display.
+ Gravity.applyDisplay(mAttrs.gravity, df, frame);
+
+ // Make sure the content and visible frames are inside of the
+ // final window frame.
+ if (content.left < frame.left) content.left = frame.left;
+ if (content.top < frame.top) content.top = frame.top;
+ if (content.right > frame.right) content.right = frame.right;
+ if (content.bottom > frame.bottom) content.bottom = frame.bottom;
+ if (visible.left < frame.left) visible.left = frame.left;
+ if (visible.top < frame.top) visible.top = frame.top;
+ if (visible.right > frame.right) visible.right = frame.right;
+ if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
+
+ final Rect contentInsets = mContentInsets;
+ contentInsets.left = content.left-frame.left;
+ contentInsets.top = content.top-frame.top;
+ contentInsets.right = frame.right-content.right;
+ contentInsets.bottom = frame.bottom-content.bottom;
+
+ final Rect visibleInsets = mVisibleInsets;
+ visibleInsets.left = visible.left-frame.left;
+ visibleInsets.top = visible.top-frame.top;
+ visibleInsets.right = frame.right-visible.right;
+ visibleInsets.bottom = frame.bottom-visible.bottom;
+
+ if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
+ mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getWidth(),
+ mService.mDisplay.getHeight(), false);
+ }
+
+ if (WindowManagerService.localLOGV) {
+ //if ("com.google.android.youtube".equals(mAttrs.packageName)
+ // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
+ + mRequestedWidth + ", mRequestedheight="
+ + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
+ + "): frame=" + mFrame.toShortString()
+ + " ci=" + contentInsets.toShortString()
+ + " vi=" + visibleInsets.toShortString());
+ //}
+ }
+ }
+
+ public Rect getFrameLw() {
+ return mFrame;
+ }
+
+ public Rect getShownFrameLw() {
+ return mShownFrame;
+ }
+
+ public Rect getDisplayFrameLw() {
+ return mDisplayFrame;
+ }
+
+ public Rect getContentFrameLw() {
+ return mContentFrame;
+ }
+
+ public Rect getVisibleFrameLw() {
+ return mVisibleFrame;
+ }
+
+ public boolean getGivenInsetsPendingLw() {
+ return mGivenInsetsPending;
+ }
+
+ public Rect getGivenContentInsetsLw() {
+ return mGivenContentInsets;
+ }
+
+ public Rect getGivenVisibleInsetsLw() {
+ return mGivenVisibleInsets;
+ }
+
+ public WindowManager.LayoutParams getAttrs() {
+ return mAttrs;
+ }
+
+ public int getSurfaceLayer() {
+ return mLayer;
+ }
+
+ public IApplicationToken getAppToken() {
+ return mAppToken != null ? mAppToken.appToken : null;
+ }
+
+ public long getInputDispatchingTimeoutNanos() {
+ return mAppToken != null
+ ? mAppToken.inputDispatchingTimeoutNanos
+ : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ }
+
+ public boolean hasAppShownWindows() {
+ return mAppToken != null ? mAppToken.firstWindowDrawn : false;
+ }
+
+ public void setAnimation(Animation anim) {
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+ mAnimating = false;
+ mLocalAnimating = false;
+ mAnimation = anim;
+ mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+ mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
+ }
+
+ public void clearAnimation() {
+ if (mAnimation != null) {
+ mAnimating = true;
+ mLocalAnimating = false;
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+ }
+
+ Surface createSurfaceLocked() {
+ if (mSurface == null) {
+ mReportDestroySurface = false;
+ mSurfacePendingDestroy = false;
+ mDrawPending = true;
+ mCommitDrawPending = false;
+ mReadyToShow = false;
+ if (mAppToken != null) {
+ mAppToken.allDrawn = false;
+ }
+
+ int flags = 0;
+
+ if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ flags |= Surface.SECURE;
+ }
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
+ WindowManagerService.TAG, "Creating surface in session "
+ + mSession.mSurfaceSession + " window " + this
+ + " w=" + mFrame.width()
+ + " h=" + mFrame.height() + " format="
+ + mAttrs.format + " flags=" + flags);
+
+ int w = mFrame.width();
+ int h = mFrame.height();
+ if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
+ // for a scaled surface, we always want the requested
+ // size.
+ w = mRequestedWidth;
+ h = mRequestedHeight;
+ }
+
+ // Something is wrong and SurfaceFlinger will not like this,
+ // try to revert to sane values
+ if (w <= 0) w = 1;
+ if (h <= 0) h = 1;
+
+ mSurfaceShown = false;
+ mSurfaceLayer = 0;
+ mSurfaceAlpha = 1;
+ mSurfaceX = 0;
+ mSurfaceY = 0;
+ mSurfaceW = w;
+ mSurfaceH = h;
+ try {
+ final boolean isHwAccelerated = (mAttrs.flags &
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
+ final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
+ if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) {
+ flags |= Surface.OPAQUE;
+ }
+ mSurface = new Surface(
+ mSession.mSurfaceSession, mSession.mPid,
+ mAttrs.getTitle().toString(),
+ 0, w, h, format, flags);
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " CREATE SURFACE "
+ + mSurface + " IN SESSION "
+ + mSession.mSurfaceSession
+ + ": pid=" + mSession.mPid + " format="
+ + mAttrs.format + " flags=0x"
+ + Integer.toHexString(flags)
+ + " / " + this);
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface");
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create");
+ return null;
+ } catch (Exception e) {
+ Slog.e(WindowManagerService.TAG, "Exception creating surface", e);
+ return null;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Got surface: " + mSurface
+ + ", set left=" + mFrame.left + " top=" + mFrame.top
+ + ", animLayer=" + mAnimLayer);
+ if (WindowManagerService.SHOW_TRANSACTIONS) {
+ Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+ WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
+ mFrame.width() + "x" + mFrame.height() + "), layer=" +
+ mAnimLayer + " HIDE", null);
+ }
+ Surface.openTransaction();
+ try {
+ try {
+ mSurfaceX = mFrame.left + mXOffset;
+ mSurfaceY = mFrame.top + mYOffset;
+ mSurface.setPosition(mSurfaceX, mSurfaceY);
+ mSurfaceLayer = mAnimLayer;
+ mSurface.setLayer(mAnimLayer);
+ mSurfaceShown = false;
+ mSurface.hide();
+ if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DITHER", null);
+ mSurface.setFlags(Surface.SURFACE_DITHER,
+ Surface.SURFACE_DITHER);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e);
+ mService.reclaimSomeSurfaceMemoryLocked(this, "create-init");
+ }
+ mLastHidden = true;
+ } finally {
+ Surface.closeTransaction();
+ if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
+ }
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Created surface " + this);
+ }
+ return mSurface;
+ }
+
+ void destroySurfaceLocked() {
+ if (mAppToken != null && this == mAppToken.startingWindow) {
+ mAppToken.startingDisplayed = false;
+ }
+
+ if (mSurface != null) {
+ mDrawPending = false;
+ mCommitDrawPending = false;
+ mReadyToShow = false;
+
+ int i = mChildWindows.size();
+ while (i > 0) {
+ i--;
+ WindowState c = mChildWindows.get(i);
+ c.mAttachedHidden = true;
+ }
+
+ if (mReportDestroySurface) {
+ mReportDestroySurface = false;
+ mSurfacePendingDestroy = true;
+ try {
+ mClient.dispatchGetNewSurface();
+ // We'll really destroy on the next time around.
+ return;
+ } catch (RemoteException e) {
+ }
+ }
+
+ try {
+ if (WindowManagerService.DEBUG_VISIBILITY) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface "
+ + mSurface + ", session " + mSession, e);
+ }
+ if (WindowManagerService.SHOW_TRANSACTIONS) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DESTROY", e);
+ }
+ mSurface.destroy();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this
+ + " surface " + mSurface + " session " + mSession
+ + ": " + e.toString());
+ }
+
+ mSurfaceShown = false;
+ mSurface = null;
+ }
+ }
+
+ boolean finishDrawingLocked() {
+ if (mDrawPending) {
+ if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
+ WindowManagerService.TAG, "finishDrawingLocked: " + mSurface);
+ mCommitDrawPending = true;
+ mDrawPending = false;
+ return true;
+ }
+ return false;
+ }
+
+ // This must be called while inside a transaction.
+ boolean commitFinishDrawingLocked(long currentTime) {
+ //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
+ if (!mCommitDrawPending) {
+ return false;
+ }
+ mCommitDrawPending = false;
+ mReadyToShow = true;
+ final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
+ final AppWindowToken atoken = mAppToken;
+ if (atoken == null || atoken.allDrawn || starting) {
+ performShowLocked();
+ }
+ return true;
+ }
+
+ // This must be called while inside a transaction.
+ boolean performShowLocked() {
+ if (WindowManagerService.DEBUG_VISIBILITY) {
+ RuntimeException e = null;
+ if (!WindowManagerService.HIDE_STACK_CRAWLS) {
+ e = new RuntimeException();
+ e.fillInStackTrace();
+ }
+ Slog.v(WindowManagerService.TAG, "performShow on " + this
+ + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
+ + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
+ }
+ if (mReadyToShow && isReadyForDisplay()) {
+ if (WindowManagerService.SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) WindowManagerService.logSurface(this,
+ "SHOW (performShowLocked)", null);
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
+ + " during animation: policyVis=" + mPolicyVisibility
+ + " attHidden=" + mAttachedHidden
+ + " tok.hiddenRequested="
+ + (mAppToken != null ? mAppToken.hiddenRequested : false)
+ + " tok.hidden="
+ + (mAppToken != null ? mAppToken.hidden : false)
+ + " animating=" + mAnimating
+ + " tok animating="
+ + (mAppToken != null ? mAppToken.animating : false));
+ if (!mService.showSurfaceRobustlyLocked(this)) {
+ return false;
+ }
+ mLastAlpha = -1;
+ mHasDrawn = true;
+ mLastHidden = false;
+ mReadyToShow = false;
+ mService.enableScreenIfNeededLocked();
+
+ mService.applyEnterAnimationLocked(this);
+
+ int i = mChildWindows.size();
+ while (i > 0) {
+ i--;
+ WindowState c = mChildWindows.get(i);
+ if (c.mAttachedHidden) {
+ c.mAttachedHidden = false;
+ if (c.mSurface != null) {
+ c.performShowLocked();
+ // It hadn't been shown, which means layout not
+ // performed on it, so now we want to make sure to
+ // do a layout. If called from within the transaction
+ // loop, this will cause it to restart with a new
+ // layout.
+ mService.mLayoutNeeded = true;
+ }
+ }
+ }
+
+ if (mAttrs.type != TYPE_APPLICATION_STARTING
+ && mAppToken != null) {
+ mAppToken.firstWindowDrawn = true;
+
+ if (mAppToken.startingData != null) {
+ if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+ "Finish starting " + mToken
+ + ": first real window is shown, no animation");
+ // If this initial window is animating, stop it -- we
+ // will do an animation to reveal it from behind the
+ // starting window, so there is no need for it to also
+ // be doing its own stuff.
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ // Make sure we clean up the animation.
+ mAnimating = true;
+ }
+ mService.mFinishedStarting.add(mAppToken);
+ mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+ mAppToken.updateReportedVisibilityLocked();
+ }
+ }
+ return true;
+ }
+
+ // This must be called while inside a transaction. Returns true if
+ // there is more animation to run.
+ boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+ if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOn()) {
+ // We will run animations as long as the display isn't frozen.
+
+ if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
+ mHasTransformation = true;
+ mHasLocalTransformation = true;
+ if (!mLocalAnimating) {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Starting animation in " + this +
+ " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
+ " dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale);
+ mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
+ mAnimation.setStartTime(currentTime);
+ mLocalAnimating = true;
+ mAnimating = true;
+ }
+ mTransformation.clear();
+ final boolean more = mAnimation.getTransformation(
+ currentTime, mTransformation);
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Stepped animation in " + this +
+ ": more=" + more + ", xform=" + mTransformation);
+ if (more) {
+ // we're not done!
+ return true;
+ }
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Finished animation in " + this +
+ " @ " + currentTime);
+
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+ //WindowManagerService.this.dump();
+ }
+ mHasLocalTransformation = false;
+ if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
+ && mAppToken.animation != null) {
+ // When our app token is animating, we kind-of pretend like
+ // we are as well. Note the mLocalAnimating mAnimationIsEntrance
+ // part of this check means that we will only do this if
+ // our window is not currently exiting, or it is not
+ // locally animating itself. The idea being that one that
+ // is exiting and doing a local animation should be removed
+ // once that animation is done.
+ mAnimating = true;
+ mHasTransformation = true;
+ mTransformation.clear();
+ return false;
+ } else if (mHasTransformation) {
+ // Little trick to get through the path below to act like
+ // we have finished an animation.
+ mAnimating = true;
+ } else if (isAnimating()) {
+ mAnimating = true;
+ }
+ } else if (mAnimation != null) {
+ // If the display is frozen, and there is a pending animation,
+ // clear it and make sure we run the cleanup code.
+ mAnimating = true;
+ mLocalAnimating = true;
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+
+ if (!mAnimating && !mLocalAnimating) {
+ return false;
+ }
+
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mExiting
+ + ", reportedVisible="
+ + (mAppToken != null ? mAppToken.reportedVisible : false));
+
+ mAnimating = false;
+ mLocalAnimating = false;
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ }
+ mAnimLayer = mLayer;
+ if (mIsImWindow) {
+ mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
+ } else if (mIsWallpaper) {
+ mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
+ }
+ if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this
+ + " anim layer: " + mAnimLayer);
+ mHasTransformation = false;
+ mHasLocalTransformation = false;
+ if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
+ if (WindowManagerService.DEBUG_VISIBILITY) {
+ Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": "
+ + mPolicyVisibilityAfterAnim);
+ }
+ mPolicyVisibility = mPolicyVisibilityAfterAnim;
+ if (!mPolicyVisibility) {
+ if (mService.mCurrentFocus == this) {
+ mService.mFocusMayChange = true;
+ }
+ // Window is no longer visible -- make sure if we were waiting
+ // for it to be displayed before enabling the display, that
+ // we allow the display to be enabled now.
+ mService.enableScreenIfNeededLocked();
+ }
+ }
+ mTransformation.clear();
+ if (mHasDrawn
+ && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
+ && mAppToken != null
+ && mAppToken.firstWindowDrawn
+ && mAppToken.startingData != null) {
+ if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting "
+ + mToken + ": first real window done animating");
+ mService.mFinishedStarting.add(mAppToken);
+ mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ }
+
+ finishExit();
+
+ if (mAppToken != null) {
+ mAppToken.updateReportedVisibilityLocked();
+ }
+
+ return false;
+ }
+
+ void finishExit() {
+ if (WindowManagerService.DEBUG_ANIM) Slog.v(
+ WindowManagerService.TAG, "finishExit in " + this
+ + ": exiting=" + mExiting
+ + " remove=" + mRemoveOnExit
+ + " windowAnimating=" + isWindowAnimating());
+
+ final int N = mChildWindows.size();
+ for (int i=0; i<N; i++) {
+ mChildWindows.get(i).finishExit();
+ }
+
+ if (!mExiting) {
+ return;
+ }
+
+ if (isWindowAnimating()) {
+ return;
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Exit animation finished in " + this
+ + ": remove=" + mRemoveOnExit);
+ if (mSurface != null) {
+ mService.mDestroySurface.add(this);
+ mDestroying = true;
+ if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "HIDE (finishExit)", null);
+ mSurfaceShown = false;
+ try {
+ mSurface.hide();
+ } catch (RuntimeException e) {
+ Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e);
+ }
+ mLastHidden = true;
+ }
+ mExiting = false;
+ if (mRemoveOnExit) {
+ mService.mPendingRemove.add(this);
+ mRemoveOnExit = false;
+ }
+ }
+
+ boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+ if (dsdx < .99999f || dsdx > 1.00001f) return false;
+ if (dtdy < .99999f || dtdy > 1.00001f) return false;
+ if (dtdx < -.000001f || dtdx > .000001f) return false;
+ if (dsdy < -.000001f || dsdy > .000001f) return false;
+ return true;
+ }
+
+ void computeShownFrameLocked() {
+ final boolean selfTransformation = mHasLocalTransformation;
+ Transformation attachedTransformation =
+ (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
+ ? mAttachedWindow.mTransformation : null;
+ Transformation appTransformation =
+ (mAppToken != null && mAppToken.hasTransformation)
+ ? mAppToken.transformation : null;
+
+ // Wallpapers are animated based on the "real" window they
+ // are currently targeting.
+ if (mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
+ && mService.mWallpaperTarget != null) {
+ if (mService.mWallpaperTarget.mHasLocalTransformation &&
+ mService.mWallpaperTarget.mAnimation != null &&
+ !mService.mWallpaperTarget.mAnimation.getDetachWallpaper()) {
+ attachedTransformation = mService.mWallpaperTarget.mTransformation;
+ if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
+ Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation);
+ }
+ }
+ if (mService.mWallpaperTarget.mAppToken != null &&
+ mService.mWallpaperTarget.mAppToken.hasTransformation &&
+ mService.mWallpaperTarget.mAppToken.animation != null &&
+ !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
+ appTransformation = mService.mWallpaperTarget.mAppToken.transformation;
+ if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
+ Slog.v(WindowManagerService.TAG, "WP target app xform: " + appTransformation);
+ }
+ }
+ }
+
+ final boolean screenAnimation = mService.mScreenRotationAnimation != null
+ && mService.mScreenRotationAnimation.isAnimating();
+ if (selfTransformation || attachedTransformation != null
+ || appTransformation != null || screenAnimation) {
+ // cache often used attributes locally
+ final Rect frame = mFrame;
+ final float tmpFloats[] = mService.mTmpFloats;
+ final Matrix tmpMatrix = mTmpMatrix;
+
+ // Compute the desired transformation.
+ tmpMatrix.setTranslate(0, 0);
+ if (selfTransformation) {
+ tmpMatrix.postConcat(mTransformation.getMatrix());
+ }
+ tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
+ if (attachedTransformation != null) {
+ tmpMatrix.postConcat(attachedTransformation.getMatrix());
+ }
+ if (appTransformation != null) {
+ tmpMatrix.postConcat(appTransformation.getMatrix());
+ }
+ if (screenAnimation) {
+ tmpMatrix.postConcat(
+ mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
+ }
+
+ // "convert" it into SurfaceFlinger's format
+ // (a 2x2 matrix + an offset)
+ // Here we must not transform the position of the surface
+ // since it is already included in the transformation.
+ //Slog.i(TAG, "Transform: " + matrix);
+
+ mHaveMatrix = true;
+ tmpMatrix.getValues(tmpFloats);
+ mDsDx = tmpFloats[Matrix.MSCALE_X];
+ mDtDx = tmpFloats[Matrix.MSKEW_Y];
+ mDsDy = tmpFloats[Matrix.MSKEW_X];
+ mDtDy = tmpFloats[Matrix.MSCALE_Y];
+ int x = (int)tmpFloats[Matrix.MTRANS_X];
+ int y = (int)tmpFloats[Matrix.MTRANS_Y];
+ int w = frame.width();
+ int h = frame.height();
+ mShownFrame.set(x, y, x+w, y+h);
+
+ // Now set the alpha... but because our current hardware
+ // can't do alpha transformation on a non-opaque surface,
+ // turn it off if we are running an animation that is also
+ // transforming since it is more important to have that
+ // animation be smooth.
+ mShownAlpha = mAlpha;
+ if (!mService.mLimitedAlphaCompositing
+ || (!PixelFormat.formatHasAlpha(mAttrs.format)
+ || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
+ && x == frame.left && y == frame.top))) {
+ //Slog.i(TAG, "Applying alpha transform");
+ if (selfTransformation) {
+ mShownAlpha *= mTransformation.getAlpha();
+ }
+ if (attachedTransformation != null) {
+ mShownAlpha *= attachedTransformation.getAlpha();
+ }
+ if (appTransformation != null) {
+ mShownAlpha *= appTransformation.getAlpha();
+ }
+ if (screenAnimation) {
+ mShownAlpha *=
+ mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
+ }
+ } else {
+ //Slog.i(TAG, "Not applying alpha transform");
+ }
+
+ if (WindowManagerService.localLOGV) Slog.v(
+ WindowManagerService.TAG, "Continuing animation in " + this +
+ ": " + mShownFrame +
+ ", alpha=" + mTransformation.getAlpha());
+ return;
+ }
+
+ mShownFrame.set(mFrame);
+ if (mXOffset != 0 || mYOffset != 0) {
+ mShownFrame.offset(mXOffset, mYOffset);
+ }
+ mShownAlpha = mAlpha;
+ mHaveMatrix = false;
+ mDsDx = 1;
+ mDtDx = 0;
+ mDsDy = 0;
+ mDtDy = 1;
+ }
+
+ /**
+ * Is this window visible? It is not visible if there is no
+ * surface, or we are in the process of running an exit animation
+ * that will remove the surface, or its app token has been hidden.
+ */
+ public boolean isVisibleLw() {
+ final AppWindowToken atoken = mAppToken;
+ return mSurface != null && mPolicyVisibility && !mAttachedHidden
+ && (atoken == null || !atoken.hiddenRequested)
+ && !mExiting && !mDestroying;
+ }
+
+ /**
+ * Like {@link #isVisibleLw}, but also counts a window that is currently
+ * "hidden" behind the keyguard as visible. This allows us to apply
+ * things like window flags that impact the keyguard.
+ * XXX I am starting to think we need to have ANOTHER visibility flag
+ * for this "hidden behind keyguard" state rather than overloading
+ * mPolicyVisibility. Ungh.
+ */
+ public boolean isVisibleOrBehindKeyguardLw() {
+ final AppWindowToken atoken = mAppToken;
+ return mSurface != null && !mAttachedHidden
+ && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
+ && !mDrawPending && !mCommitDrawPending
+ && !mExiting && !mDestroying;
+ }
+
+ /**
+ * Is this window visible, ignoring its app token? It is not visible
+ * if there is no surface, or we are in the process of running an exit animation
+ * that will remove the surface.
+ */
+ public boolean isWinVisibleLw() {
+ final AppWindowToken atoken = mAppToken;
+ return mSurface != null && mPolicyVisibility && !mAttachedHidden
+ && (atoken == null || !atoken.hiddenRequested || atoken.animating)
+ && !mExiting && !mDestroying;
+ }
+
+ /**
+ * The same as isVisible(), but follows the current hidden state of
+ * the associated app token, not the pending requested hidden state.
+ */
+ boolean isVisibleNow() {
+ return mSurface != null && mPolicyVisibility && !mAttachedHidden
+ && !mRootToken.hidden && !mExiting && !mDestroying;
+ }
+
+ /**
+ * Can this window possibly be a drag/drop target? The test here is
+ * a combination of the above "visible now" with the check that the
+ * Input Manager uses when discarding windows from input consideration.
+ */
+ boolean isPotentialDragTarget() {
+ return isVisibleNow() && (mInputChannel != null) && !mRemoved;
+ }
+
+ /**
+ * Same as isVisible(), but we also count it as visible between the
+ * call to IWindowSession.add() and the first relayout().
+ */
+ boolean isVisibleOrAdding() {
+ final AppWindowToken atoken = mAppToken;
+ return ((mSurface != null && !mReportDestroySurface)
+ || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
+ && mPolicyVisibility && !mAttachedHidden
+ && (atoken == null || !atoken.hiddenRequested)
+ && !mExiting && !mDestroying;
+ }
+
+ /**
+ * Is this window currently on-screen? It is on-screen either if it
+ * is visible or it is currently running an animation before no longer
+ * being visible.
+ */
+ boolean isOnScreen() {
+ final AppWindowToken atoken = mAppToken;
+ if (atoken != null) {
+ return mSurface != null && mPolicyVisibility && !mDestroying
+ && ((!mAttachedHidden && !atoken.hiddenRequested)
+ || mAnimation != null || atoken.animation != null);
+ } else {
+ return mSurface != null && mPolicyVisibility && !mDestroying
+ && (!mAttachedHidden || mAnimation != null);
+ }
+ }
+
+ /**
+ * Like isOnScreen(), but we don't return true if the window is part
+ * of a transition that has not yet been started.
+ */
+ boolean isReadyForDisplay() {
+ if (mRootToken.waitingToShow &&
+ mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ return false;
+ }
+ final AppWindowToken atoken = mAppToken;
+ final boolean animating = atoken != null
+ ? (atoken.animation != null) : false;
+ return mSurface != null && mPolicyVisibility && !mDestroying
+ && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
+ && !mRootToken.hidden)
+ || mAnimation != null || animating);
+ }
+
+ /** Is the window or its container currently animating? */
+ boolean isAnimating() {
+ final WindowState attached = mAttachedWindow;
+ final AppWindowToken atoken = mAppToken;
+ return mAnimation != null
+ || (attached != null && attached.mAnimation != null)
+ || (atoken != null &&
+ (atoken.animation != null
+ || atoken.inPendingTransaction));
+ }
+
+ /** Is this window currently animating? */
+ boolean isWindowAnimating() {
+ return mAnimation != null;
+ }
+
+ /**
+ * Like isOnScreen, but returns false if the surface hasn't yet
+ * been drawn.
+ */
+ public boolean isDisplayedLw() {
+ final AppWindowToken atoken = mAppToken;
+ return mSurface != null && mPolicyVisibility && !mDestroying
+ && !mDrawPending && !mCommitDrawPending
+ && ((!mAttachedHidden &&
+ (atoken == null || !atoken.hiddenRequested))
+ || mAnimating);
+ }
+
+ /**
+ * Returns true if the window has a surface that it has drawn a
+ * complete UI in to.
+ */
+ public boolean isDrawnLw() {
+ final AppWindowToken atoken = mAppToken;
+ return mSurface != null && !mDestroying
+ && !mDrawPending && !mCommitDrawPending;
+ }
+
+ /**
+ * Return true if the window is opaque and fully drawn. This indicates
+ * it may obscure windows behind it.
+ */
+ boolean isOpaqueDrawn() {
+ return (mAttrs.format == PixelFormat.OPAQUE
+ || mAttrs.type == TYPE_WALLPAPER)
+ && mSurface != null && mAnimation == null
+ && (mAppToken == null || mAppToken.animation == null)
+ && !mDrawPending && !mCommitDrawPending;
+ }
+
+ /**
+ * Return whether this window is wanting to have a translation
+ * animation applied to it for an in-progress move. (Only makes
+ * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
+ */
+ boolean shouldAnimateMove() {
+ return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen
+ && (mFrame.top != mLastFrame.top
+ || mFrame.left != mLastFrame.left)
+ && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
+ && mService.mPolicy.isScreenOn();
+ }
+
+ boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
+ return
+ // only if the application is requesting compatible window
+ (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
+ // only if it's visible
+ mHasDrawn && mViewVisibility == View.VISIBLE &&
+ // and only if the application fills the compatible screen
+ mFrame.left <= mService.mCompatibleScreenFrame.left &&
+ mFrame.top <= mService.mCompatibleScreenFrame.top &&
+ mFrame.right >= mService.mCompatibleScreenFrame.right &&
+ mFrame.bottom >= mService.mCompatibleScreenFrame.bottom;
+ }
+
+ boolean isFullscreen(int screenWidth, int screenHeight) {
+ return mFrame.left <= 0 && mFrame.top <= 0 &&
+ mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
+ }
+
+ void removeLocked() {
+ disposeInputChannel();
+
+ if (mAttachedWindow != null) {
+ if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
+ mAttachedWindow.mChildWindows.remove(this);
+ }
+ destroySurfaceLocked();
+ mSession.windowRemovedLocked();
+ try {
+ mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
+ } catch (RuntimeException e) {
+ // Ignore if it has already been removed (usually because
+ // we are doing this as part of processing a death note.)
+ }
+ }
+
+ void disposeInputChannel() {
+ if (mInputChannel != null) {
+ mService.mInputManager.unregisterInputChannel(mInputChannel);
+
+ mInputChannel.dispose();
+ mInputChannel = null;
+ }
+ }
+
+ private class DeathRecipient implements IBinder.DeathRecipient {
+ public void binderDied() {
+ try {
+ synchronized(mService.mWindowMap) {
+ WindowState win = mService.windowForClientLocked(mSession, mClient, false);
+ Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
+ if (win != null) {
+ mService.removeWindowLocked(mSession, win);
+ }
+ }
+ } catch (IllegalArgumentException ex) {
+ // This will happen if the window has already been
+ // removed.
+ }
+ }
+ }
+
+ /** Returns true if this window desires key events. */
+ public final boolean canReceiveKeys() {
+ return isVisibleOrAdding()
+ && (mViewVisibility == View.VISIBLE)
+ && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
+ }
+
+ public boolean hasDrawnLw() {
+ return mHasDrawn;
+ }
+
+ public boolean showLw(boolean doAnimation) {
+ return showLw(doAnimation, true);
+ }
+
+ boolean showLw(boolean doAnimation, boolean requestAnim) {
+ if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
+ return false;
+ }
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
+ if (doAnimation) {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
+ + mPolicyVisibility + " mAnimation=" + mAnimation);
+ if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+ doAnimation = false;
+ } else if (mPolicyVisibility && mAnimation == null) {
+ // Check for the case where we are currently visible and
+ // not animating; we do not want to do animation at such a
+ // point to become visible when we already are.
+ doAnimation = false;
+ }
+ }
+ mPolicyVisibility = true;
+ mPolicyVisibilityAfterAnim = true;
+ if (doAnimation) {
+ mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
+ }
+ if (requestAnim) {
+ mService.requestAnimationLocked(0);
+ }
+ return true;
+ }
+
+ public boolean hideLw(boolean doAnimation) {
+ return hideLw(doAnimation, true);
+ }
+
+ boolean hideLw(boolean doAnimation, boolean requestAnim) {
+ if (doAnimation) {
+ if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
+ doAnimation = false;
+ }
+ }
+ boolean current = doAnimation ? mPolicyVisibilityAfterAnim
+ : mPolicyVisibility;
+ if (!current) {
+ return false;
+ }
+ if (doAnimation) {
+ mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
+ if (mAnimation == null) {
+ doAnimation = false;
+ }
+ }
+ if (doAnimation) {
+ mPolicyVisibilityAfterAnim = false;
+ } else {
+ if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
+ mPolicyVisibilityAfterAnim = false;
+ mPolicyVisibility = false;
+ // Window is no longer visible -- make sure if we were waiting
+ // for it to be displayed before enabling the display, that
+ // we allow the display to be enabled now.
+ mService.enableScreenIfNeededLocked();
+ if (mService.mCurrentFocus == this) {
+ mService.mFocusMayChange = true;
+ }
+ }
+ if (requestAnim) {
+ mService.requestAnimationLocked(0);
+ }
+ return true;
+ }
+
+ public void getTouchableRegion(Region outRegion) {
+ final Rect frame = mFrame;
+ switch (mTouchableInsets) {
+ default:
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
+ outRegion.set(frame);
+ break;
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
+ final Rect inset = mGivenContentInsets;
+ outRegion.set(
+ frame.left + inset.left, frame.top + inset.top,
+ frame.right - inset.right, frame.bottom - inset.bottom);
+ break;
+ }
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
+ final Rect inset = mGivenVisibleInsets;
+ outRegion.set(
+ frame.left + inset.left, frame.top + inset.top,
+ frame.right - inset.right, frame.bottom - inset.bottom);
+ break;
+ }
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
+ final Region givenTouchableRegion = mGivenTouchableRegion;
+ outRegion.set(givenTouchableRegion);
+ outRegion.translate(frame.left, frame.top);
+ break;
+ }
+ }
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mSession="); pw.print(mSession);
+ pw.print(" mClient="); pw.println(mClient.asBinder());
+ pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
+ if (mAttachedWindow != null || mLayoutAttached) {
+ pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
+ pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
+ }
+ if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
+ pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
+ pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
+ pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
+ pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
+ }
+ pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
+ pw.print(" mSubLayer="); pw.print(mSubLayer);
+ pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
+ pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
+ : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+ pw.print("="); pw.print(mAnimLayer);
+ pw.print(" mLastLayer="); pw.println(mLastLayer);
+ if (mSurface != null) {
+ pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+ pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
+ pw.print(" layer="); pw.print(mSurfaceLayer);
+ pw.print(" alpha="); pw.print(mSurfaceAlpha);
+ pw.print(" rect=("); pw.print(mSurfaceX);
+ pw.print(","); pw.print(mSurfaceY);
+ pw.print(") "); pw.print(mSurfaceW);
+ pw.print(" x "); pw.println(mSurfaceH);
+ }
+ pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+ pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
+ if (mAppToken != null) {
+ pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+ }
+ if (mTargetAppToken != null) {
+ pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
+ }
+ pw.print(prefix); pw.print("mViewVisibility=0x");
+ pw.print(Integer.toHexString(mViewVisibility));
+ pw.print(" mLastHidden="); pw.print(mLastHidden);
+ pw.print(" mHaveFrame="); pw.print(mHaveFrame);
+ pw.print(" mObscured="); pw.println(mObscured);
+ if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
+ pw.print(prefix); pw.print("mPolicyVisibility=");
+ pw.print(mPolicyVisibility);
+ pw.print(" mPolicyVisibilityAfterAnim=");
+ pw.print(mPolicyVisibilityAfterAnim);
+ pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
+ }
+ if (!mRelayoutCalled) {
+ pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
+ }
+ pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
+ pw.print(" h="); pw.print(mRequestedHeight);
+ pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+ if (mXOffset != 0 || mYOffset != 0) {
+ pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
+ pw.print(" y="); pw.println(mYOffset);
+ }
+ pw.print(prefix); pw.print("mGivenContentInsets=");
+ mGivenContentInsets.printShortString(pw);
+ pw.print(" mGivenVisibleInsets=");
+ mGivenVisibleInsets.printShortString(pw);
+ pw.println();
+ if (mTouchableInsets != 0 || mGivenInsetsPending) {
+ pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
+ pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
+ }
+ pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
+ pw.print(prefix); pw.print("mShownFrame=");
+ mShownFrame.printShortString(pw);
+ pw.print(" last="); mLastShownFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
+ pw.print(" last="); mLastFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContainingFrame=");
+ mContainingFrame.printShortString(pw);
+ pw.print(" mParentFrame=");
+ mParentFrame.printShortString(pw);
+ pw.print(" mDisplayFrame=");
+ mDisplayFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
+ pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
+ pw.print(" last="); mLastContentInsets.printShortString(pw);
+ pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
+ pw.print(" last="); mLastVisibleInsets.printShortString(pw);
+ pw.println();
+ if (mAnimating || mLocalAnimating || mAnimationIsEntrance
+ || mAnimation != null) {
+ pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
+ pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
+ pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
+ pw.print(" mAnimation="); pw.println(mAnimation);
+ }
+ if (mHasTransformation || mHasLocalTransformation) {
+ pw.print(prefix); pw.print("XForm: has=");
+ pw.print(mHasTransformation);
+ pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
+ pw.print(" "); mTransformation.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);
+ pw.print(" mLastAlpha="); pw.println(mLastAlpha);
+ }
+ if (mHaveMatrix) {
+ pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx);
+ pw.print(" mDtDx="); pw.print(mDtDx);
+ pw.print(" mDsDy="); pw.print(mDsDy);
+ pw.print(" mDtDy="); pw.println(mDtDy);
+ }
+ pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
+ pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
+ pw.print(" mReadyToShow="); pw.print(mReadyToShow);
+ pw.print(" mHasDrawn="); pw.println(mHasDrawn);
+ if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
+ pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
+ pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
+ pw.print(" mDestroying="); pw.print(mDestroying);
+ pw.print(" mRemoved="); pw.println(mRemoved);
+ }
+ if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
+ pw.print(prefix); pw.print("mOrientationChanging=");
+ pw.print(mOrientationChanging);
+ pw.print(" mAppFreezing="); pw.print(mAppFreezing);
+ pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
+ }
+ if (mHScale != 1 || mVScale != 1) {
+ pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
+ pw.print(" mVScale="); pw.println(mVScale);
+ }
+ if (mWallpaperX != -1 || mWallpaperY != -1) {
+ pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
+ pw.print(" mWallpaperY="); pw.println(mWallpaperY);
+ }
+ if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
+ pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
+ pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
+ }
+ }
+
+ String makeInputChannelName() {
+ return Integer.toHexString(System.identityHashCode(this))
+ + " " + mAttrs.getTitle();
+ }
+
+ @Override
+ public String toString() {
+ if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
+ || mWasPaused != mToken.paused) {
+ mLastTitle = mAttrs.getTitle();
+ mWasPaused = mToken.paused;
+ mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
+ + " " + mLastTitle + " paused=" + mWasPaused + "}";
+ }
+ return mStringNameCache;
+ }
+}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowToken.java b/services/java/com/android/server/wm/WindowToken.java
new file mode 100644
index 0000000..3cd256e
--- /dev/null
+++ b/services/java/com/android/server/wm/WindowToken.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.os.IBinder;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Container of a set of related windows in the window manager. Often this
+ * is an AppWindowToken, which is the handle for an Activity that it uses
+ * to display windows. For nested windows, there is a WindowToken created for
+ * the parent window to manage its children.
+ */
+class WindowToken {
+ // The window manager!
+ final WindowManagerService service;
+
+ // The actual token.
+ final IBinder token;
+
+ // The type of window this token is for, as per WindowManager.LayoutParams.
+ final int windowType;
+
+ // Set if this token was explicitly added by a client, so should
+ // not be removed when all windows are removed.
+ final boolean explicit;
+
+ // For printing.
+ String stringName;
+
+ // If this is an AppWindowToken, this is non-null.
+ AppWindowToken appWindowToken;
+
+ // All of the windows associated with this token.
+ final ArrayList<WindowState> windows = new ArrayList<WindowState>();
+
+ // Is key dispatching paused for this token?
+ boolean paused = false;
+
+ // Should this token's windows be hidden?
+ boolean hidden;
+
+ // Temporary for finding which tokens no longer have visible windows.
+ boolean hasVisible;
+
+ // Set to true when this token is in a pending transaction where it
+ // will be shown.
+ boolean waitingToShow;
+
+ // Set to true when this token is in a pending transaction where it
+ // will be hidden.
+ boolean waitingToHide;
+
+ // Set to true when this token is in a pending transaction where its
+ // windows will be put to the bottom of the list.
+ boolean sendingToBottom;
+
+ // Set to true when this token is in a pending transaction where its
+ // windows will be put to the top of the list.
+ boolean sendingToTop;
+
+ WindowToken(WindowManagerService _service, IBinder _token, int type, boolean _explicit) {
+ service = _service;
+ token = _token;
+ windowType = type;
+ explicit = _explicit;
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("token="); pw.println(token);
+ pw.print(prefix); pw.print("windows="); pw.println(windows);
+ pw.print(prefix); pw.print("windowType="); pw.print(windowType);
+ pw.print(" hidden="); pw.print(hidden);
+ pw.print(" hasVisible="); pw.println(hasVisible);
+ if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
+ pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
+ pw.print(" waitingToHide="); pw.print(waitingToHide);
+ pw.print(" sendingToBottom="); pw.print(sendingToBottom);
+ pw.print(" sendingToTop="); pw.println(sendingToTop);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (stringName == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("WindowToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" token="); sb.append(token); sb.append('}');
+ stringName = sb.toString();
+ }
+ return stringName;
+ }
+}
\ No newline at end of file