Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wm;
     18 
     19 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     20 
     21 import com.android.server.wm.WindowManagerService.H;
     22 
     23 import android.content.pm.ActivityInfo;
     24 import android.os.Message;
     25 import android.os.RemoteException;
     26 import android.util.Slog;
     27 import android.view.IApplicationToken;
     28 import android.view.View;
     29 import android.view.WindowManager;
     30 import android.view.animation.Animation;
     31 import android.view.animation.Transformation;
     32 
     33 import java.io.PrintWriter;
     34 import java.util.ArrayList;
     35 
     36 /**
     37  * Version of WindowToken that is specifically for a particular application (or
     38  * really activity) that is displaying windows.
     39  */
     40 class AppWindowToken extends WindowToken {
     41     // Non-null only for application tokens.
     42     final IApplicationToken appToken;
     43 
     44     // All of the windows and child windows that are included in this
     45     // application token.  Note this list is NOT sorted!
     46     final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
     47 
     48     int groupId = -1;
     49     boolean appFullscreen;
     50     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     51 
     52     // The input dispatching timeout for this application token in nanoseconds.
     53     long inputDispatchingTimeoutNanos;
     54 
     55     // These are used for determining when all windows associated with
     56     // an activity have been drawn, so they can be made visible together
     57     // at the same time.
     58     int lastTransactionSequence;
     59     int numInterestingWindows;
     60     int numDrawnWindows;
     61     boolean inPendingTransaction;
     62     boolean allDrawn;
     63 
     64     // Is this token going to be hidden in a little while?  If so, it
     65     // won't be taken into account for setting the screen orientation.
     66     boolean willBeHidden;
     67 
     68     // Is this window's surface needed?  This is almost like hidden, except
     69     // it will sometimes be true a little earlier: when the token has
     70     // been shown, but is still waiting for its app transition to execute
     71     // before making its windows shown.
     72     boolean hiddenRequested;
     73 
     74     // Have we told the window clients to hide themselves?
     75     boolean clientHidden;
     76 
     77     // Last visibility state we reported to the app token.
     78     boolean reportedVisible;
     79 
     80     // Last drawn state we reported to the app token.
     81     boolean reportedDrawn;
     82 
     83     // Set to true when the token has been removed from the window mgr.
     84     boolean removed;
     85 
     86     // Have we been asked to have this token keep the screen frozen?
     87     boolean freezingScreen;
     88 
     89     boolean animating;
     90     Animation animation;
     91     boolean hasTransformation;
     92     final Transformation transformation = new Transformation();
     93 
     94     // Offset to the window of all layers in the token, for use by
     95     // AppWindowToken animations.
     96     int animLayerAdjustment;
     97 
     98     // Information about an application starting window if displayed.
     99     StartingData startingData;
    100     WindowState startingWindow;
    101     View startingView;
    102     boolean startingDisplayed;
    103     boolean startingMoved;
    104     boolean firstWindowDrawn;
    105 
    106     // Input application handle used by the input dispatcher.
    107     final InputApplicationHandle mInputApplicationHandle;
    108 
    109     AppWindowToken(WindowManagerService _service, IApplicationToken _token) {
    110         super(_service, _token.asBinder(),
    111                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
    112         appWindowToken = this;
    113         appToken = _token;
    114         mInputApplicationHandle = new InputApplicationHandle(this);
    115         lastTransactionSequence = service.mTransactionSequence-1;
    116     }
    117 
    118     public void setAnimation(Animation anim) {
    119         if (WindowManagerService.localLOGV) Slog.v(
    120             WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
    121         animation = anim;
    122         animating = false;
    123         anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
    124         anim.scaleCurrentDuration(service.mTransitionAnimationScale);
    125         int zorder = anim.getZAdjustment();
    126         int adj = 0;
    127         if (zorder == Animation.ZORDER_TOP) {
    128             adj = WindowManagerService.TYPE_LAYER_OFFSET;
    129         } else if (zorder == Animation.ZORDER_BOTTOM) {
    130             adj = -WindowManagerService.TYPE_LAYER_OFFSET;
    131         }
    132 
    133         if (animLayerAdjustment != adj) {
    134             animLayerAdjustment = adj;
    135             updateLayers();
    136         }
    137     }
    138 
    139     public void setDummyAnimation() {
    140         if (animation == null) {
    141             if (WindowManagerService.localLOGV) Slog.v(
    142                 WindowManagerService.TAG, "Setting dummy animation in " + this);
    143             animation = WindowManagerService.sDummyAnimation;
    144         }
    145     }
    146 
    147     public void clearAnimation() {
    148         if (animation != null) {
    149             animation = null;
    150             animating = true;
    151         }
    152     }
    153 
    154     void updateLayers() {
    155         final int N = allAppWindows.size();
    156         final int adj = animLayerAdjustment;
    157         for (int i=0; i<N; i++) {
    158             WindowState w = allAppWindows.get(i);
    159             w.mAnimLayer = w.mLayer + adj;
    160             if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
    161                     + w.mAnimLayer);
    162             if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
    163                 service.setInputMethodAnimLayerAdjustment(adj);
    164             }
    165             if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
    166                 service.setWallpaperAnimLayerAdjustmentLocked(adj);
    167             }
    168         }
    169     }
    170 
    171     void sendAppVisibilityToClients() {
    172         final int N = allAppWindows.size();
    173         for (int i=0; i<N; i++) {
    174             WindowState win = allAppWindows.get(i);
    175             if (win == startingWindow && clientHidden) {
    176                 // Don't hide the starting window.
    177                 continue;
    178             }
    179             try {
    180                 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
    181                         "Setting visibility of " + win + ": " + (!clientHidden));
    182                 win.mClient.dispatchAppVisibility(!clientHidden);
    183             } catch (RemoteException e) {
    184             }
    185         }
    186     }
    187 
    188     void showAllWindowsLocked() {
    189         final int NW = allAppWindows.size();
    190         for (int i=0; i<NW; i++) {
    191             WindowState w = allAppWindows.get(i);
    192             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
    193                     "performing show on: " + w);
    194             w.performShowLocked();
    195         }
    196     }
    197 
    198     // This must be called while inside a transaction.
    199     boolean stepAnimationLocked(long currentTime, int dw, int dh) {
    200         if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
    201             // We will run animations as long as the display isn't frozen.
    202 
    203             if (animation == WindowManagerService.sDummyAnimation) {
    204                 // This guy is going to animate, but not yet.  For now count
    205                 // it as not animating for purposes of scheduling transactions;
    206                 // when it is really time to animate, this will be set to
    207                 // a real animation and the next call will execute normally.
    208                 return false;
    209             }
    210 
    211             if ((allDrawn || animating || startingDisplayed) && animation != null) {
    212                 if (!animating) {
    213                     if (WindowManagerService.DEBUG_ANIM) Slog.v(
    214                         WindowManagerService.TAG, "Starting animation in " + this +
    215                         " @ " + currentTime + ": dw=" + dw + " dh=" + dh
    216                         + " scale=" + service.mTransitionAnimationScale
    217                         + " allDrawn=" + allDrawn + " animating=" + animating);
    218                     animation.initialize(dw, dh, dw, dh);
    219                     animation.setStartTime(currentTime);
    220                     animating = true;
    221                 }
    222                 transformation.clear();
    223                 final boolean more = animation.getTransformation(
    224                     currentTime, transformation);
    225                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
    226                     WindowManagerService.TAG, "Stepped animation in " + this +
    227                     ": more=" + more + ", xform=" + transformation);
    228                 if (more) {
    229                     // we're done!
    230                     hasTransformation = true;
    231                     return true;
    232                 }
    233                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
    234                     WindowManagerService.TAG, "Finished animation in " + this +
    235                     " @ " + currentTime);
    236                 animation = null;
    237             }
    238         } else if (animation != null) {
    239             // If the display is frozen, and there is a pending animation,
    240             // clear it and make sure we run the cleanup code.
    241             animating = true;
    242             animation = null;
    243         }
    244 
    245         hasTransformation = false;
    246 
    247         if (!animating) {
    248             return false;
    249         }
    250 
    251         clearAnimation();
    252         animating = false;
    253         if (animLayerAdjustment != 0) {
    254             animLayerAdjustment = 0;
    255             updateLayers();
    256         }
    257         if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
    258             service.moveInputMethodWindowsIfNeededLocked(true);
    259         }
    260 
    261         if (WindowManagerService.DEBUG_ANIM) Slog.v(
    262                 WindowManagerService.TAG, "Animation done in " + this
    263                 + ": reportedVisible=" + reportedVisible);
    264 
    265         transformation.clear();
    266 
    267         final int N = windows.size();
    268         for (int i=0; i<N; i++) {
    269             windows.get(i).finishExit();
    270         }
    271         updateReportedVisibilityLocked();
    272 
    273         return false;
    274     }
    275 
    276     void updateReportedVisibilityLocked() {
    277         if (appToken == null) {
    278             return;
    279         }
    280 
    281         int numInteresting = 0;
    282         int numVisible = 0;
    283         int numDrawn = 0;
    284         boolean nowGone = true;
    285 
    286         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
    287         final int N = allAppWindows.size();
    288         for (int i=0; i<N; i++) {
    289             WindowState win = allAppWindows.get(i);
    290             if (win == startingWindow || win.mAppFreezing
    291                     || win.mViewVisibility != View.VISIBLE
    292                     || win.mAttrs.type == TYPE_APPLICATION_STARTING
    293                     || win.mDestroying) {
    294                 continue;
    295             }
    296             if (WindowManagerService.DEBUG_VISIBILITY) {
    297                 Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
    298                         + win.isDrawnLw()
    299                         + ", isAnimating=" + win.isAnimating());
    300                 if (!win.isDrawnLw()) {
    301                     Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mSurface
    302                             + " pv=" + win.mPolicyVisibility
    303                             + " dp=" + win.mDrawPending
    304                             + " cdp=" + win.mCommitDrawPending
    305                             + " ah=" + win.mAttachedHidden
    306                             + " th="
    307                             + (win.mAppToken != null
    308                                     ? win.mAppToken.hiddenRequested : false)
    309                             + " a=" + win.mAnimating);
    310                 }
    311             }
    312             numInteresting++;
    313             if (win.isDrawnLw()) {
    314                 numDrawn++;
    315                 if (!win.isAnimating()) {
    316                     numVisible++;
    317                 }
    318                 nowGone = false;
    319             } else if (win.isAnimating()) {
    320                 nowGone = false;
    321             }
    322         }
    323 
    324         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
    325         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
    326         if (!nowGone) {
    327             // If the app is not yet gone, then it can only become visible/drawn.
    328             if (!nowDrawn) {
    329                 nowDrawn = reportedDrawn;
    330             }
    331             if (!nowVisible) {
    332                 nowVisible = reportedVisible;
    333             }
    334         }
    335         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
    336                 + numInteresting + " visible=" + numVisible);
    337         if (nowDrawn != reportedDrawn) {
    338             if (nowDrawn) {
    339                 Message m = service.mH.obtainMessage(
    340                         H.REPORT_APPLICATION_TOKEN_DRAWN, this);
    341                 service.mH.sendMessage(m);
    342             }
    343             reportedDrawn = nowDrawn;
    344         }
    345         if (nowVisible != reportedVisible) {
    346             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
    347                     WindowManagerService.TAG, "Visibility changed in " + this
    348                     + ": vis=" + nowVisible);
    349             reportedVisible = nowVisible;
    350             Message m = service.mH.obtainMessage(
    351                     H.REPORT_APPLICATION_TOKEN_WINDOWS,
    352                     nowVisible ? 1 : 0,
    353                     nowGone ? 1 : 0,
    354                     this);
    355             service.mH.sendMessage(m);
    356         }
    357     }
    358 
    359     WindowState findMainWindow() {
    360         int j = windows.size();
    361         while (j > 0) {
    362             j--;
    363             WindowState win = windows.get(j);
    364             if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
    365                     || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    366                 return win;
    367             }
    368         }
    369         return null;
    370     }
    371 
    372     void dump(PrintWriter pw, String prefix) {
    373         super.dump(pw, prefix);
    374         if (appToken != null) {
    375             pw.print(prefix); pw.println("app=true");
    376         }
    377         if (allAppWindows.size() > 0) {
    378             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
    379         }
    380         pw.print(prefix); pw.print("groupId="); pw.print(groupId);
    381                 pw.print(" appFullscreen="); pw.print(appFullscreen);
    382                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
    383         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
    384                 pw.print(" clientHidden="); pw.print(clientHidden);
    385                 pw.print(" willBeHidden="); pw.print(willBeHidden);
    386                 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
    387                 pw.print(" reportedVisible="); pw.println(reportedVisible);
    388         if (paused || freezingScreen) {
    389             pw.print(prefix); pw.print("paused="); pw.print(paused);
    390                     pw.print(" freezingScreen="); pw.println(freezingScreen);
    391         }
    392         if (numInterestingWindows != 0 || numDrawnWindows != 0
    393                 || inPendingTransaction || allDrawn) {
    394             pw.print(prefix); pw.print("numInterestingWindows=");
    395                     pw.print(numInterestingWindows);
    396                     pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
    397                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
    398                     pw.print(" allDrawn="); pw.println(allDrawn);
    399         }
    400         if (animating || animation != null) {
    401             pw.print(prefix); pw.print("animating="); pw.print(animating);
    402                     pw.print(" animation="); pw.println(animation);
    403         }
    404         if (hasTransformation) {
    405             pw.print(prefix); pw.print("XForm: ");
    406                     transformation.printShortString(pw);
    407                     pw.println();
    408         }
    409         if (animLayerAdjustment != 0) {
    410             pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
    411         }
    412         if (startingData != null || removed || firstWindowDrawn) {
    413             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
    414                     pw.print(" removed="); pw.print(removed);
    415                     pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
    416         }
    417         if (startingWindow != null || startingView != null
    418                 || startingDisplayed || startingMoved) {
    419             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
    420                     pw.print(" startingView="); pw.print(startingView);
    421                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
    422                     pw.print(" startingMoved"); pw.println(startingMoved);
    423         }
    424     }
    425 
    426     @Override
    427     public String toString() {
    428         if (stringName == null) {
    429             StringBuilder sb = new StringBuilder();
    430             sb.append("AppWindowToken{");
    431             sb.append(Integer.toHexString(System.identityHashCode(this)));
    432             sb.append(" token="); sb.append(token); sb.append('}');
    433             stringName = sb.toString();
    434         }
    435         return stringName;
    436     }
    437 }