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.input.InputApplicationHandle;
     22 import com.android.server.wm.WindowManagerService.H;
     23 
     24 import android.content.pm.ActivityInfo;
     25 import android.os.Message;
     26 import android.os.RemoteException;
     27 import android.util.Slog;
     28 import android.view.IApplicationToken;
     29 import android.view.View;
     30 import android.view.WindowManager;
     31 
     32 import java.io.PrintWriter;
     33 import java.util.ArrayList;
     34 
     35 class AppTokenList extends ArrayList<AppWindowToken> {
     36 }
     37 
     38 /**
     39  * Version of WindowToken that is specifically for a particular application (or
     40  * really activity) that is displaying windows.
     41  */
     42 class AppWindowToken extends WindowToken {
     43     // Non-null only for application tokens.
     44     final IApplicationToken appToken;
     45 
     46     // All of the windows and child windows that are included in this
     47     // application token.  Note this list is NOT sorted!
     48     final WindowList allAppWindows = new WindowList();
     49     final AppWindowAnimator mAppAnimator;
     50 
     51     final WindowAnimator mAnimator;
     52 
     53     final boolean voiceInteraction;
     54 
     55     int groupId = -1;
     56     boolean appFullscreen;
     57     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     58     boolean layoutConfigChanges;
     59     boolean showWhenLocked;
     60 
     61     // The input dispatching timeout for this application token in nanoseconds.
     62     long inputDispatchingTimeoutNanos;
     63 
     64     // These are used for determining when all windows associated with
     65     // an activity have been drawn, so they can be made visible together
     66     // at the same time.
     67     // initialize so that it doesn't match mTransactionSequence which is an int.
     68     long lastTransactionSequence = Long.MIN_VALUE;
     69     int numInterestingWindows;
     70     int numDrawnWindows;
     71     boolean inPendingTransaction;
     72     boolean allDrawn;
     73     // Set to true when this app creates a surface while in the middle of an animation. In that
     74     // case do not clear allDrawn until the animation completes.
     75     boolean deferClearAllDrawn;
     76 
     77     // Is this token going to be hidden in a little while?  If so, it
     78     // won't be taken into account for setting the screen orientation.
     79     boolean willBeHidden;
     80 
     81     // Is this window's surface needed?  This is almost like hidden, except
     82     // it will sometimes be true a little earlier: when the token has
     83     // been shown, but is still waiting for its app transition to execute
     84     // before making its windows shown.
     85     boolean hiddenRequested;
     86 
     87     // Have we told the window clients to hide themselves?
     88     boolean clientHidden;
     89 
     90     // Last visibility state we reported to the app token.
     91     boolean reportedVisible;
     92 
     93     // Last drawn state we reported to the app token.
     94     boolean reportedDrawn;
     95 
     96     // Set to true when the token has been removed from the window mgr.
     97     boolean removed;
     98 
     99     // Information about an application starting window if displayed.
    100     StartingData startingData;
    101     WindowState startingWindow;
    102     View startingView;
    103     boolean startingDisplayed;
    104     boolean startingMoved;
    105     boolean firstWindowDrawn;
    106 
    107     // Input application handle used by the input dispatcher.
    108     final InputApplicationHandle mInputApplicationHandle;
    109 
    110     boolean mDeferRemoval;
    111 
    112     boolean mLaunchTaskBehind;
    113     boolean mEnteringAnimation;
    114 
    115     AppWindowToken(WindowManagerService _service, IApplicationToken _token,
    116             boolean _voiceInteraction) {
    117         super(_service, _token.asBinder(),
    118                 WindowManager.LayoutParams.TYPE_APPLICATION, true);
    119         appWindowToken = this;
    120         appToken = _token;
    121         voiceInteraction = _voiceInteraction;
    122         mInputApplicationHandle = new InputApplicationHandle(this);
    123         mAnimator = service.mAnimator;
    124         mAppAnimator = new AppWindowAnimator(this);
    125     }
    126 
    127     void sendAppVisibilityToClients() {
    128         final int N = allAppWindows.size();
    129         for (int i=0; i<N; i++) {
    130             WindowState win = allAppWindows.get(i);
    131             if (win == startingWindow && clientHidden) {
    132                 // Don't hide the starting window.
    133                 continue;
    134             }
    135             try {
    136                 if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
    137                         "Setting visibility of " + win + ": " + (!clientHidden));
    138                 win.mClient.dispatchAppVisibility(!clientHidden);
    139             } catch (RemoteException e) {
    140             }
    141         }
    142     }
    143 
    144     void updateReportedVisibilityLocked() {
    145         if (appToken == null) {
    146             return;
    147         }
    148 
    149         int numInteresting = 0;
    150         int numVisible = 0;
    151         int numDrawn = 0;
    152         boolean nowGone = true;
    153 
    154         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
    155                 "Update reported visibility: " + this);
    156         final int N = allAppWindows.size();
    157         for (int i=0; i<N; i++) {
    158             WindowState win = allAppWindows.get(i);
    159             if (win == startingWindow || win.mAppFreezing
    160                     || win.mViewVisibility != View.VISIBLE
    161                     || win.mAttrs.type == TYPE_APPLICATION_STARTING
    162                     || win.mDestroying) {
    163                 continue;
    164             }
    165             if (WindowManagerService.DEBUG_VISIBILITY) {
    166                 Slog.v(WindowManagerService.TAG, "Win " + win + ": isDrawn="
    167                         + win.isDrawnLw()
    168                         + ", isAnimating=" + win.mWinAnimator.isAnimating());
    169                 if (!win.isDrawnLw()) {
    170                     Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mWinAnimator.mSurfaceControl
    171                             + " pv=" + win.mPolicyVisibility
    172                             + " mDrawState=" + win.mWinAnimator.mDrawState
    173                             + " ah=" + win.mAttachedHidden
    174                             + " th="
    175                             + (win.mAppToken != null
    176                                     ? win.mAppToken.hiddenRequested : false)
    177                             + " a=" + win.mWinAnimator.mAnimating);
    178                 }
    179             }
    180             numInteresting++;
    181             if (win.isDrawnLw()) {
    182                 numDrawn++;
    183                 if (!win.mWinAnimator.isAnimating()) {
    184                     numVisible++;
    185                 }
    186                 nowGone = false;
    187             } else if (win.mWinAnimator.isAnimating()) {
    188                 nowGone = false;
    189             }
    190         }
    191 
    192         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
    193         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
    194         if (!nowGone) {
    195             // If the app is not yet gone, then it can only become visible/drawn.
    196             if (!nowDrawn) {
    197                 nowDrawn = reportedDrawn;
    198             }
    199             if (!nowVisible) {
    200                 nowVisible = reportedVisible;
    201             }
    202         }
    203         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
    204                 + numInteresting + " visible=" + numVisible);
    205         if (nowDrawn != reportedDrawn) {
    206             if (nowDrawn) {
    207                 Message m = service.mH.obtainMessage(
    208                         H.REPORT_APPLICATION_TOKEN_DRAWN, this);
    209                 service.mH.sendMessage(m);
    210             }
    211             reportedDrawn = nowDrawn;
    212         }
    213         if (nowVisible != reportedVisible) {
    214             if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
    215                     WindowManagerService.TAG, "Visibility changed in " + this
    216                     + ": vis=" + nowVisible);
    217             reportedVisible = nowVisible;
    218             Message m = service.mH.obtainMessage(
    219                     H.REPORT_APPLICATION_TOKEN_WINDOWS,
    220                     nowVisible ? 1 : 0,
    221                     nowGone ? 1 : 0,
    222                     this);
    223             service.mH.sendMessage(m);
    224         }
    225     }
    226 
    227     WindowState findMainWindow() {
    228         int j = windows.size();
    229         while (j > 0) {
    230             j--;
    231             WindowState win = windows.get(j);
    232             if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
    233                     || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    234                 return win;
    235             }
    236         }
    237         return null;
    238     }
    239 
    240     boolean isVisible() {
    241         final int N = allAppWindows.size();
    242         for (int i=0; i<N; i++) {
    243             WindowState win = allAppWindows.get(i);
    244             if (!win.mAppFreezing
    245                     && (win.mViewVisibility == View.VISIBLE ||
    246                         (win.mWinAnimator.isAnimating() &&
    247                                 !service.mAppTransition.isTransitionSet()))
    248                     && !win.mDestroying && win.isDrawnLw()) {
    249                 return true;
    250             }
    251         }
    252         return false;
    253     }
    254 
    255     @Override
    256     void removeAllWindows() {
    257         for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
    258                 // removeWindowLocked at bottom of loop may remove multiple entries from
    259                 // allAppWindows if the window to be removed has child windows. It also may
    260                 // not remove any windows from allAppWindows at all if win is exiting and
    261                 // currently animating away. This ensures that winNdx is monotonically decreasing
    262                 // and never beyond allAppWindows bounds.
    263                 winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
    264             WindowState win = allAppWindows.get(winNdx);
    265             if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
    266                 Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win);
    267             }
    268 
    269             win.mService.removeWindowLocked(win.mSession, win);
    270         }
    271     }
    272 
    273     @Override
    274     void dump(PrintWriter pw, String prefix) {
    275         super.dump(pw, prefix);
    276         if (appToken != null) {
    277             pw.print(prefix); pw.print("app=true voiceInteraction="); pw.println(voiceInteraction);
    278         }
    279         if (allAppWindows.size() > 0) {
    280             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
    281         }
    282         pw.print(prefix); pw.print("groupId="); pw.print(groupId);
    283                 pw.print(" appFullscreen="); pw.print(appFullscreen);
    284                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
    285         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
    286                 pw.print(" clientHidden="); pw.print(clientHidden);
    287                 pw.print(" willBeHidden="); pw.print(willBeHidden);
    288                 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
    289                 pw.print(" reportedVisible="); pw.println(reportedVisible);
    290         if (paused) {
    291             pw.print(prefix); pw.print("paused="); pw.println(paused);
    292         }
    293         if (numInterestingWindows != 0 || numDrawnWindows != 0
    294                 || allDrawn || mAppAnimator.allDrawn) {
    295             pw.print(prefix); pw.print("numInterestingWindows=");
    296                     pw.print(numInterestingWindows);
    297                     pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
    298                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
    299                     pw.print(" allDrawn="); pw.print(allDrawn);
    300                     pw.print(" (animator="); pw.print(mAppAnimator.allDrawn);
    301                     pw.println(")");
    302         }
    303         if (inPendingTransaction) {
    304             pw.print(prefix); pw.print("inPendingTransaction=");
    305                     pw.println(inPendingTransaction);
    306         }
    307         if (startingData != null || removed || firstWindowDrawn || mDeferRemoval) {
    308             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
    309                     pw.print(" removed="); pw.print(removed);
    310                     pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
    311                     pw.print(" mDeferRemoval="); pw.println(mDeferRemoval);
    312         }
    313         if (startingWindow != null || startingView != null
    314                 || startingDisplayed || startingMoved) {
    315             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
    316                     pw.print(" startingView="); pw.print(startingView);
    317                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
    318                     pw.print(" startingMoved"); pw.println(startingMoved);
    319         }
    320     }
    321 
    322     @Override
    323     public String toString() {
    324         if (stringName == null) {
    325             StringBuilder sb = new StringBuilder();
    326             sb.append("AppWindowToken{");
    327             sb.append(Integer.toHexString(System.identityHashCode(this)));
    328             sb.append(" token="); sb.append(token); sb.append('}');
    329             stringName = sb.toString();
    330         }
    331         return stringName;
    332     }
    333 }
    334