WindowManagerService.java revision 85b764e22babfe5508286fbad5d7fee12345704f
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.wm;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static android.view.WindowManager.LayoutParams.*;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
210795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
220795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport android.app.AppOpsManager;
230795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport android.util.ArraySet;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TimeUtils;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowId;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowSessionCallback;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowContentFrameStats;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IBatteryStats;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.policy.PolicyManager;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.policy.impl.PhoneWindowManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.FastPrintWriter;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputContext;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodClient;
35242d65bf9faf1d2bc3468490e510551140e23462San Mehatimport com.android.internal.view.IInputMethodManager;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.WindowManagerPolicyThread;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.AttributeCache;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.DisplayThread;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.EventLogTags;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.LocalServices;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.UiThread;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.Watchdog;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.am.BatteryStatsService;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.input.InputManagerService;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.power.ShutdownThread;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.Manifest;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.IActivityManager;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.StatusBarManager;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.admin.DevicePolicyManager;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.animation.ValueAnimator;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
54957e58670baad8c5995f1368e3b5280f0dbd891fSan Mehatimport android.content.ContentResolver;
55a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehatimport android.content.Context;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ActivityInfo;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.CompatibilityInfo;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap.Config;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Matrix;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Point;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Region;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.hardware.display.DisplayManager;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.hardware.display.DisplayManagerInternal;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Debug;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
79e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.IRemoteCallback;
80e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Looper;
81e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Message;
82e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Parcel;
83e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.ParcelFileDescriptor;
84e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.PowerManager;
85e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.PowerManagerInternal;
86e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Process;
87e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.RemoteException;
88e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.ServiceManager;
89e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.StrictMode;
90e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.SystemClock;
91e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.SystemProperties;
92e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Trace;
93e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.UserHandle;
94e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.WorkSource;
95e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.provider.Settings;
96e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.DisplayMetrics;
97e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.EventLog;
98e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.Log;
99e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.SparseArray;
100e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.Pair;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Slog;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseIntArray;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Choreographer;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Display;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.DisplayInfo;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IApplicationToken;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IInputFilter;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IOnKeyguardExitResult;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IRotationWatcher;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindow;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowSession;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.InputChannel;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.InputDevice;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.InputEvent;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.InputEventReceiver;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MagnificationSpec;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManagerInternal;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface.OutOfResourcesException;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Surface;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceControl;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SurfaceSession;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewTreeObserver;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManagerGlobal;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManagerPolicy;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager.LayoutParams;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManagerPolicy.FakeWindow;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManagerPolicy.PointerEventListener;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.Animation;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.AnimationUtils;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.Transformation;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedWriter;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.DataInputStream;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStreamWriter;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.StringWriter;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.text.DateFormat;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Date;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** {@hide} */
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WindowManagerService extends IWindowManager.Stub
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final String TAG = "WindowManager";
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_ADD_REMOVE = false;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_FOCUS = false;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_ANIM = false;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_LAYOUT = false;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_RESIZE = false;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_LAYERS = false;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_INPUT = false;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_INPUT_METHOD = false;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_VISIBILITY = false;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_WINDOW_MOVEMENT = false;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_TOKEN_MOVEMENT = false;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_ORIENTATION = false;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_APP_ORIENTATION = false;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_CONFIGURATION = false;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_APP_TRANSITIONS = false;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_STARTING_WINDOW = false;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_REORDER = false;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_WALLPAPER = false;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_DRAG = false;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_SCREEN_ON = false;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_SCREENSHOT = false;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_BOOT = false;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_LAYOUT_REPEATS = true;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_SURFACE_TRACE = false;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_WINDOW_TRACE = false;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_TASK_MOVEMENT = false;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG_STACK = false;
192e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final boolean DEBUG_DISPLAY = false;
193e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final boolean SHOW_SURFACE_ALLOC = false;
194e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final boolean SHOW_TRANSACTIONS = false;
195e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
196e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final boolean HIDE_STACK_CRAWLS = true;
197e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    static final int LAYOUT_REPEAT_THRESHOLD = 4;
198e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
199242d65bf9faf1d2bc3468490e510551140e23462San Mehat    static final boolean PROFILE_ORIENTATION = false;
200242d65bf9faf1d2bc3468490e510551140e23462San Mehat    static final boolean localLOGV = DEBUG;
201242d65bf9faf1d2bc3468490e510551140e23462San Mehat
202242d65bf9faf1d2bc3468490e510551140e23462San Mehat    /** How much to multiply the policy's type layer, to reserve room
203e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat     * for multiple windows of the same type and Z-ordering adjustment
204e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat     * with TYPE_LAYER_OFFSET. */
2053e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int TYPE_LAYER_MULTIPLIER = 10000;
2063e458241d9930465a20a861ecb42744355d48e48San Mehat
2073e458241d9930465a20a861ecb42744355d48e48San Mehat    /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
2083e458241d9930465a20a861ecb42744355d48e48San Mehat     * or below others in the same layer. */
2093e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int TYPE_LAYER_OFFSET = 1000;
2103e458241d9930465a20a861ecb42744355d48e48San Mehat
2113e458241d9930465a20a861ecb42744355d48e48San Mehat    /** How much to increment the layer for each window, to reserve room
2123e458241d9930465a20a861ecb42744355d48e48San Mehat     * for effect surfaces between them.
2133e458241d9930465a20a861ecb42744355d48e48San Mehat     */
2143e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int WINDOW_LAYER_MULTIPLIER = 5;
2153e458241d9930465a20a861ecb42744355d48e48San Mehat
2163e458241d9930465a20a861ecb42744355d48e48San Mehat    /**
217a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * Dim surface layer is immediately below target window.
218a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
219a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    static final int LAYER_OFFSET_DIM = 1;
220a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
221a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    /**
222a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * Blur surface layer is immediately below dim layer.
223a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
224a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    static final int LAYER_OFFSET_BLUR = 2;
225a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
226a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    /**
227a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * FocusedStackFrame layer is immediately above focused window.
228a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
229a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    static final int LAYER_OFFSET_FOCUSED_STACK = 1;
230a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
231a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    /**
232a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * Animation thumbnail is as far as possible below the window above
233a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * the thumbnail (or in other words as far as possible above the window
234a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * below it).
235a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
236a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    static final int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER-1;
2373e458241d9930465a20a861ecb42744355d48e48San Mehat
2383e458241d9930465a20a861ecb42744355d48e48San Mehat    /**
2391fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat     * Layer at which to put the rotation freeze snapshot.
2401fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat     */
2411fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat    static final int FREEZE_LAYER = (TYPE_LAYER_MULTIPLIER * 200) + 1;
2423e458241d9930465a20a861ecb42744355d48e48San Mehat
2433e458241d9930465a20a861ecb42744355d48e48San Mehat    /**
2443e458241d9930465a20a861ecb42744355d48e48San Mehat     * Layer at which to put the mask for emulated screen sizes.
2453e458241d9930465a20a861ecb42744355d48e48San Mehat     */
2467e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    static final int MASK_LAYER = TYPE_LAYER_MULTIPLIER * 200;
2477e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
2487e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /** The maximum length we will accept for a loaded animation duration:
2493e458241d9930465a20a861ecb42744355d48e48San Mehat     * this is 10 seconds.
2503e458241d9930465a20a861ecb42744355d48e48San Mehat     */
2517e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    static final int MAX_ANIMATION_DURATION = 10*1000;
2527e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
2537e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /** Amount of time (in milliseconds) to animate the fade-in-out transition for
2547e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     * compatible windows.
2557e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     */
2567e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
2571fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat
2587e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
2597e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
2607e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
2617e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /**
2627e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     * If true, the window manager will do its own custom freezing and general
2637e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     * management of the screen during rotation.
2647e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     */
2657e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    static final boolean CUSTOM_SCREEN_ROTATION = true;
266242d65bf9faf1d2bc3468490e510551140e23462San Mehat
267242d65bf9faf1d2bc3468490e510551140e23462San Mehat    // Maximum number of milliseconds to wait for input devices to be enumerated before
268242d65bf9faf1d2bc3468490e510551140e23462San Mehat    // proceding with safe mode detection.
269242d65bf9faf1d2bc3468490e510551140e23462San Mehat    private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
2703e458241d9930465a20a861ecb42744355d48e48San Mehat
2713e458241d9930465a20a861ecb42744355d48e48San Mehat    // Default input dispatching timeout in nanoseconds.
2723e458241d9930465a20a861ecb42744355d48e48San Mehat    static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
2733e458241d9930465a20a861ecb42744355d48e48San Mehat
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Minimum value for attachStack and resizeStack weight value */
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final float STACK_WEIGHT_MIN = 0.2f;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
277242d65bf9faf1d2bc3468490e510551140e23462San Mehat    /** Maximum value for attachStack and resizeStack weight value */
278242d65bf9faf1d2bc3468490e510551140e23462San Mehat    public static final float STACK_WEIGHT_MAX = 0.8f;
2797d619f18a277ee3114624df7301db94db83936b9San Mehat
280242d65bf9faf1d2bc3468490e510551140e23462San Mehat    static final int UPDATE_FOCUS_NORMAL = 0;
2817d619f18a277ee3114624df7301db94db83936b9San Mehat    static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
282242d65bf9faf1d2bc3468490e510551140e23462San Mehat    static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
283242d65bf9faf1d2bc3468490e510551140e23462San Mehat    static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
284242d65bf9faf1d2bc3468490e510551140e23462San Mehat
285242d65bf9faf1d2bc3468490e510551140e23462San Mehat    private static final String SYSTEM_SECURE = "ro.secure";
286242d65bf9faf1d2bc3468490e510551140e23462San Mehat    private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
287e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
288e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    private static final String DENSITY_OVERRIDE = "ro.config.density_override";
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String SIZE_OVERRIDE = "ro.config.size_override";
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SCREENSHOT_RETRIES = 3;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The flag describing a full screen app window (where the app takes care of drawing under the
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // SystemUI bars)
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final private KeyguardDisableHandler mKeyguardDisableHandler;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String action = intent.getAction();
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) {
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyguardDisableHandler.sendEmptyMessage(
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Current user when multi-user is enabled. Don't show windows of
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * non-current user. Also see mCurrentProfileIds.
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurrentUserId;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Users that are profiles of the current user. These are also allowed to show windows
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * on the current user.
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean mHaveInputMethods;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean mAllowBootMessages;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean mLimitedAlphaCompositing;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IActivityManager mActivityManager;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IBatteryStats mBatteryStats;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final AppOpsManager mAppOps;
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplaySettings mDisplaySettings;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All currently active sessions with clients.
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArraySet<Session> mSessions = new ArraySet<Session>();
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from an IWindow IBinder to the server's Window object.
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is also used as the lock for all of our state.
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from a token IBinder to a WindowToken object.
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * List of window tokens that have finished starting their application,
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and now need to have the policy remove their windows.
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fake windows added to the window manager.  Note: ordered from top to
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bottom, opposite of mWindows.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows that are being resized.  Used so we can tell the client about
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the resize after closing the transaction in which we resized the
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * underlying surface.
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows whose animations have ended and now must be removed.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3820bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen     * Stacks whose animations have ended and whose tasks, apps, selves may now be removed.
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArraySet<TaskStack> mPendingStacksRemove = new ArraySet<TaskStack>();
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Used when processing mPendingRemove to avoid working on the original array.
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState[] mPendingRemoveTmp = new WindowState[20];
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows whose surface should be destroyed.
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows that have lost input focus and are waiting for the new
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * focus window to be displayed before they are told about this.
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4020bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen    /**
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is set when we have run out of memory, and will either be an empty
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * list or contain windows that need to be force removed.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<WindowState> mForceRemoves;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows that clients are waiting to have drawn.
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>();
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * And the callback to make when they've all been drawn.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Runnable mWaitingForDrawnCallback;
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Windows that have called relayout() while we were running animations,
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so we need to tell when the animation is done.
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4210bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen    final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Used when rebuilding window list to keep track of windows that have
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * been removed.
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState[] mRebuildTmp = new WindowState[20];
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Stores for each user whether screencapture is disabled
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This array is essentially a cache for all userId for
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<Boolean>();
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethodManager mInputMethodManager;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AccessibilityController mAccessibilityController;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SurfaceSession mFxSession;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Watermark mWatermark;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    StrictModeFlash mStrictModeFlash;
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CircularDisplayMask mCircularDisplayMask;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    FocusedStackFrame mFocusedStackFrame;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mFocusedStackLayer;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final float[] mTmpFloats = new float[9];
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Rect mTmpContentRect = new Rect();
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mDisplayReady;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mSafeMode;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mDisplayEnabled = false;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mSystemBooted = false;
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mForceDisplayEnabled = false;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowingBootMessages = false;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mLastANRState;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** All DisplayContents in the world, kept here */
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mRotation = 0;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mAltOrientation = false;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mKeyguardWaitingForActivityDrawn;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class RotationWatcher {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IRotationWatcher watcher;
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IBinder.DeathRecipient deathRecipient;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RotationWatcher(IRotationWatcher w, IBinder.DeathRecipient d) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            watcher = w;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            deathRecipient = d;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>();
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mDeferredRotationPauseCount;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mSystemDecorLayer = 0;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Rect mScreenRect = new Rect();
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mTraversalScheduled = false;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mDisplayFrozen = false;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mDisplayFreezeTime = 0;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLastDisplayFreezeDuration = 0;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Object mLastFinishedFreezeSource = null;
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWaitingForConfig = false;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mWindowsFreezingScreen = false;
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mClientFreezingScreen = false;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mAppsFreezingScreen = 0;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLayoutSeq = 0;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mLastStatusBarVisibility = 0;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // State while inside of layoutAndPlaceSurfacesLocked().
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mFocusMayChange;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Configuration mCurConfiguration = new Configuration();
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is held as long as we have the screen frozen, to give us time to
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // perform a rotation animation when turning off shows the lock screen which
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // changes the orientation.
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final PowerManager.WakeLock mScreenFrozenLock;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final AppTransition mAppTransition;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mStartingIconInTransition = false;
510add868cebaf62cffe96e79764ea0b7f2320a03ebAmith Yamasani    boolean mSkipAppTransitionAnimation = false;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>();
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>();
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mIsTouchDevice;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final H mH = new H();
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Choreographer mChoreographer = Choreographer.getInstance();
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mCurrentFocus = null;
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mLastFocus = null;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** This just indicates the window the input method is on top of, not
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * necessarily the window its input is going to. */
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mInputMethodTarget = null;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** If true hold off on modifying the animation layer of mInputMethodTarget */
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputMethodTargetWaitingAnim;
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mInputMethodAnimLayerAdjustment;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mInputMethodWindow = null;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHardKeyboardAvailable;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowImeWithHardKeyboard;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SettingsObserver mSettingsObserver;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class SettingsObserver extends ContentObserver {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public SettingsObserver() {
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(new Handler());
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onChange(boolean selfChange) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateShowImeWithHardKeyboard();
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If non-null, this is the currently visible window that is associated
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // with the wallpaper.
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mWallpaperTarget = null;
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If non-null, we are in the middle of animating from one wallpaper target
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // to another, and this is the lower one in Z-order.
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mLowerWallpaperTarget = null;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // If non-null, we are in the middle of animating from one wallpaper target
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // to another, and this is the higher one in Z-order.
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mUpperWallpaperTarget = null;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mWallpaperAnimLayerAdjustment;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mLastWallpaperX = -1;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mLastWallpaperY = -1;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mLastWallpaperXStep = -1;
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mLastWallpaperYStep = -1;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is set when we are waiting for a wallpaper to tell us it is done
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // changing its scroll position.
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    WindowState mWaitingOnWallpaper;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The last time we had a timeout when waiting for a wallpaper.
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastWallpaperTimeoutTime;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We give a wallpaper up to 150ms to finish scrolling.
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final long WALLPAPER_TIMEOUT = 150;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Time we wait after a timeout before trying to wait again.
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mAnimateWallpaperWithTarget;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AppWindowToken mFocusedApp = null;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PowerManager mPowerManager;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PowerManagerInternal mPowerManagerInternal;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mWindowAnimationScaleSetting = 1.0f;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mTransitionAnimationScaleSetting = 1.0f;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    float mAnimatorDurationScaleSetting = 1.0f;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mAnimationsDisabled = false;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final InputManagerService mInputManager;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayManagerInternal mDisplayManagerInternal;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final DisplayManager mDisplayManager;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Who is holding the screen on.
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Session mHoldingScreenOn;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PowerManager.WakeLock mHoldingScreenWakeLock;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mTurnOnScreen;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DragState mDragState = null;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // For frozen screen animations.
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mExitAnimId, mEnterAnimId;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * methods. */
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class LayoutFields {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_UPDATE_ROTATION                = 1 << 0;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_ORIENTATION_CHANGE_COMPLETE    = 1 << 3;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_TURN_ON_SCREEN                 = 1 << 4;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        static final int SET_WALLPAPER_ACTION_PENDING       = 1 << 5;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mWallpaperForceHidingChanged = false;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mWallpaperMayChange = false;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mOrientationChangeComplete = true;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Object mLastWindowFreezeSource = null;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private Session mHoldScreen = null;
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mObscured = false;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mSyswin = false;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mScreenBrightness = -1;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private float mButtonBrightness = -1;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mUserActivityTimeout = -1;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mUpdateRotation = false;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mWallpaperActionPending = false;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set to true when the display contains content to show the user.
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // When false, the display manager may choose to mirror or blank the display.
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mDisplayHasContent = false;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
638c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        // Only set while traversing the default display based on its content.
639c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        // Affects the behavior of mirroring on secondary displays.
640c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        boolean mObscureApplicationContentOnSecondaryDisplays = false;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float mPreferredRefreshRate = 0;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final LayoutFields mInnerFields = new LayoutFields();
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mAnimationScheduled;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTransactionSequence;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Only do a maximum of 6 repeated layouts. After that quit */
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLayoutRepeatCount;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final WindowAnimator mAnimator;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** All of the TaskStacks in the window manager, unordered. For an ordered list call
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * DisplayContent.getStacks(). */
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final PointerEventDispatcher mPointerEventDispatcher;
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WindowContentFrameStats mTempWindowRenderStats;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final class DragInputEventReceiver extends InputEventReceiver {
668c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(inputChannel, looper);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onInputEvent(InputEvent event) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean handled = false;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (event instanceof MotionEvent
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        && mDragState != null) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final MotionEvent motionEvent = (MotionEvent)event;
680c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                    boolean endDrag = false;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final float newX = motionEvent.getRawX();
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    final float newY = motionEvent.getRawY();
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (motionEvent.getAction()) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case MotionEvent.ACTION_DOWN: {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG_DRAG) {
687c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                            Slog.w(TAG, "Unexpected ACTION_DOWN in drag layer");
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } break;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case MotionEvent.ACTION_MOVE: {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized (mWindowMap) {
693c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                            // move the surface and tell the involved window(s) where we are
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mDragState.notifyMoveLw(newX, newY);
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } break;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case MotionEvent.ACTION_UP: {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
700c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                                + newX + "," + newY);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized (mWindowMap) {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endDrag = mDragState.notifyDropLw(newX, newY);
703c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                        }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } break;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case MotionEvent.ACTION_CANCEL: {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG_DRAG) Slog.d(TAG, "Drag cancelled!");
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        endDrag = true;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } break;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (endDrag) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // tell all the windows that the drag has ended
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        synchronized (mWindowMap) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mDragState.endDragLw();
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handled = true;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Slog.e(TAG, "Exception caught by drag handleMotion", e);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                finishInputEvent(event, handled);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether the UI is currently running in touch mode (not showing
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * navigational focus because the user is directly pressing the screen).
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInTouchMode = true;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ViewServer mViewServer;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final ArrayList<WindowChangeListener> mWindowChangeListeners =
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new ArrayList<WindowChangeListener>();
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mWindowsChanged = false;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface WindowChangeListener {
742c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        public void windowsChanged();
743c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        public void focusChanged();
744c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    }
745c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
746c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    final Configuration mTempConfiguration = new Configuration();
747c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
748c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    // The desired scaling factor for compatible apps.
749c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    float mCompatibleScreenScale;
750c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
751c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    // If true, only the core apps and services are being launched because the device
752c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    // is in a special boot mode, such as being encrypted or waiting for a decryption password.
753c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    // For example, when this flag is true, there will be no wallpaper service.
754c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    final boolean mOnlyCore;
755c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
756c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    public static WindowManagerService main(final Context context,
757c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            final InputManagerService im,
758c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            final boolean haveInputMethods, final boolean showBootMsgs,
759c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            final boolean onlyCore) {
760c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        final WindowManagerService[] holder = new WindowManagerService[1];
761c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        DisplayThread.getHandler().runWithScissors(new Runnable() {
762c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            @Override
763c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            public void run() {
764c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                holder[0] = new WindowManagerService(context, im,
765c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                        haveInputMethods, showBootMsgs, onlyCore);
766c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            }
767c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        }, 0);
768c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        return holder[0];
769c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    }
770c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
771c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    private void initPolicy() {
772c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        UiThread.getHandler().runWithScissors(new Runnable() {
773c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            @Override
774c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            public void run() {
775c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
776c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
777c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
778c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
779c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                        * TYPE_LAYER_MULTIPLIER
780c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                        + TYPE_LAYER_OFFSET;
781c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            }
782c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        }, 0);
783c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    }
784c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
785c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    private WindowManagerService(Context context, InputManagerService inputManager,
786c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
787c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mContext = context;
788c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mHaveInputMethods = haveInputMethods;
789c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mAllowBootMessages = showBootMsgs;
790c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mOnlyCore = onlyCore;
791c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mLimitedAlphaCompositing = context.getResources().getBoolean(
792c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                com.android.internal.R.bool.config_sf_limitedAlpha);
793c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mInputManager = inputManager; // Must be before createDisplayContentLocked.
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDisplaySettings = new DisplaySettings(context);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDisplaySettings.readSettingsLocked();
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LocalServices.addService(WindowManagerPolicy.class, mPolicy);
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFxSession = new SurfaceSession();
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Display[] displays = mDisplayManager.getDisplays();
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (Display display : displays) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createDisplayContentLocked(display);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPowerManagerInternal.registerLowPowerModeObserver(
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new PowerManagerInternal.LowPowerModeListener() {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            @Override
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void onLowPowerModeChanged(boolean enabled) {
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                synchronized (mWindowMap) {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mAnimationsDisabled != enabled) {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mAnimationsDisabled = enabled;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        dispatchNewAnimatorScaleLocked(null);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        });
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mScreenFrozenLock = mPowerManager.newWakeLock(
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mScreenFrozenLock.setReferenceCounted(false);
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAppTransition = new AppTransition(context, mH);
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mActivityManager = ActivityManagerNative.getDefault();
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBatteryStats = BatteryStatsService.getService();
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AppOpsManager.OnOpChangedInternalListener opListener =
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new AppOpsManager.OnOpChangedInternalListener() {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    @Override public void onOpChanged(int op, String packageName) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        updateAppOpsState();
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                };
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null, opListener);
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW, null, opListener);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get persisted window scale setting
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.registerReceiver(mBroadcastReceiver, filter);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSettingsObserver = new SettingsObserver();
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateShowImeWithHardKeyboard();
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHoldingScreenWakeLock = mPowerManager.newWakeLock(
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHoldingScreenWakeLock.setReferenceCounted(false);
863e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
8643e458241d9930465a20a861ecb42744355d48e48San Mehat        mAnimator = new WindowAnimator(this);
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LocalServices.addService(WindowManagerInternal.class, new LocalService());
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initPolicy();
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Add ourself to the Watchdog monitors.
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Watchdog.getInstance().addMonitor(this);
8710bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SurfaceControl.openTransaction();
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createWatermarkInTransaction();
875c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            mFocusedStackFrame = new FocusedStackFrame(
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    getDefaultDisplayContentLocked().getDisplay(), mFxSession);
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SurfaceControl.closeTransaction();
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        showCircularDisplayMaskIfNeeded();
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputMonitor getInputMonitor() {
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputMonitor;
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
894            // The window manager only throws security exceptions, so let's
895            // log all others.
896            if (!(e instanceof SecurityException)) {
897                Slog.wtf(TAG, "Window Manager Crash", e);
898            }
899            throw e;
900        }
901    }
902
903    private void placeWindowAfter(WindowState pos, WindowState window) {
904        final WindowList windows = pos.getWindowList();
905        final int i = windows.indexOf(pos);
906        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
907            TAG, "Adding window " + window + " at "
908            + (i+1) + " of " + windows.size() + " (after " + pos + ")");
909        windows.add(i+1, window);
910        mWindowsChanged = true;
911    }
912
913    private void placeWindowBefore(WindowState pos, WindowState window) {
914        final WindowList windows = pos.getWindowList();
915        int i = windows.indexOf(pos);
916        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
917            TAG, "Adding window " + window + " at "
918            + i + " of " + windows.size() + " (before " + pos + ")");
919        if (i < 0) {
920            Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
921            i = 0;
922        }
923        windows.add(i, window);
924        mWindowsChanged = true;
925    }
926
927    //This method finds out the index of a window that has the same app token as
928    //win. used for z ordering the windows in mWindows
929    private int findIdxBasedOnAppTokens(WindowState win) {
930        WindowList windows = win.getWindowList();
931        for(int j = windows.size() - 1; j >= 0; j--) {
932            WindowState wentry = windows.get(j);
933            if(wentry.mAppToken == win.mAppToken) {
934                return j;
935            }
936        }
937        return -1;
938    }
939
940    /**
941     * Return the list of Windows from the passed token on the given Display.
942     * @param token The token with all the windows.
943     * @param displayContent The display we are interested in.
944     * @return List of windows from token that are on displayContent.
945     */
946    WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
947        final WindowList windowList = new WindowList();
948        final int count = token.windows.size();
949        for (int i = 0; i < count; i++) {
950            final WindowState win = token.windows.get(i);
951            if (win.getDisplayContent() == displayContent) {
952                windowList.add(win);
953            }
954        }
955        return windowList;
956    }
957
958    /**
959     * Recursive search through a WindowList and all of its windows' children.
960     * @param targetWin The window to search for.
961     * @param windows The list to search.
962     * @return The index of win in windows or of the window that is an ancestor of win.
963     */
964    private int indexOfWinInWindowList(WindowState targetWin, WindowList windows) {
965        for (int i = windows.size() - 1; i >= 0; i--) {
966            final WindowState w = windows.get(i);
967            if (w == targetWin) {
968                return i;
969            }
970            if (!w.mChildWindows.isEmpty()) {
971                if (indexOfWinInWindowList(targetWin, w.mChildWindows) >= 0) {
972                    return i;
973                }
974            }
975        }
976        return -1;
977    }
978
979    private int addAppWindowToListLocked(final WindowState win) {
980        final IWindow client = win.mClient;
981        final WindowToken token = win.mToken;
982        final DisplayContent displayContent = win.getDisplayContent();
983        if (displayContent == null) {
984            // It doesn't matter this display is going away.
985            return 0;
986        }
987
988        final WindowList windows = win.getWindowList();
989        final int N = windows.size();
990        WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
991        int tokenWindowsPos = 0;
992        int windowListPos = tokenWindowList.size();
993        if (!tokenWindowList.isEmpty()) {
994            // If this application has existing windows, we
995            // simply place the new window on top of them... but
996            // keep the starting window on top.
997            if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
998                // Base windows go behind everything else.
999                WindowState lowestWindow = tokenWindowList.get(0);
1000                placeWindowBefore(lowestWindow, win);
1001                tokenWindowsPos = indexOfWinInWindowList(lowestWindow, token.windows);
1002            } else {
1003                AppWindowToken atoken = win.mAppToken;
1004                WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1005                if (atoken != null && lastWindow == atoken.startingWindow) {
1006                    placeWindowBefore(lastWindow, win);
1007                    tokenWindowsPos = indexOfWinInWindowList(lastWindow, token.windows);
1008                } else {
1009                    int newIdx = findIdxBasedOnAppTokens(win);
1010                    //there is a window above this one associated with the same
1011                    //apptoken note that the window could be a floating window
1012                    //that was created later or a window at the top of the list of
1013                    //windows associated with this token.
1014                    if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1015                            "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
1016                            N);
1017                    windows.add(newIdx + 1, win);
1018                    if (newIdx < 0) {
1019                        // No window from token found on win's display.
1020                        tokenWindowsPos = 0;
1021                    } else {
1022                        tokenWindowsPos = indexOfWinInWindowList(
1023                                windows.get(newIdx), token.windows) + 1;
1024                    }
1025                    mWindowsChanged = true;
1026                }
1027            }
1028            return tokenWindowsPos;
1029        }
1030
1031        // No windows from this token on this display
1032        if (localLOGV) Slog.v(TAG, "Figuring out where to add app window " + client.asBinder()
1033                + " (token=" + token + ")");
1034        // Figure out where the window should go, based on the
1035        // order of applications.
1036        WindowState pos = null;
1037
1038        final ArrayList<Task> tasks = displayContent.getTasks();
1039        int taskNdx;
1040        int tokenNdx = -1;
1041        for (taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1042            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1043            for (tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
1044                final AppWindowToken t = tokens.get(tokenNdx);
1045                if (t == token) {
1046                    --tokenNdx;
1047                    if (tokenNdx < 0) {
1048                        --taskNdx;
1049                        if (taskNdx >= 0) {
1050                            tokenNdx = tasks.get(taskNdx).mAppTokens.size() - 1;
1051                        }
1052                    }
1053                    break;
1054                }
1055
1056                // We haven't reached the token yet; if this token
1057                // is not going to the bottom and has windows on this display, we can
1058                // use it as an anchor for when we do reach the token.
1059                tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1060                if (!t.sendingToBottom && tokenWindowList.size() > 0) {
1061                    pos = tokenWindowList.get(0);
1062                }
1063            }
1064            if (tokenNdx >= 0) {
1065                // early exit
1066                break;
1067            }
1068        }
1069
1070        // We now know the index into the apps.  If we found
1071        // an app window above, that gives us the position; else
1072        // we need to look some more.
1073        if (pos != null) {
1074            // Move behind any windows attached to this one.
1075            WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1076            if (atoken != null) {
1077                tokenWindowList =
1078                        getTokenWindowsOnDisplay(atoken, displayContent);
1079                final int NC = tokenWindowList.size();
1080                if (NC > 0) {
1081                    WindowState bottom = tokenWindowList.get(0);
1082                    if (bottom.mSubLayer < 0) {
1083                        pos = bottom;
1084                    }
1085                }
1086            }
1087            placeWindowBefore(pos, win);
1088            return tokenWindowsPos;
1089        }
1090
1091        // Continue looking down until we find the first
1092        // token that has windows on this display.
1093        for ( ; taskNdx >= 0; --taskNdx) {
1094            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
1095            for ( ; tokenNdx >= 0; --tokenNdx) {
1096                final AppWindowToken t = tokens.get(tokenNdx);
1097                tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
1098                final int NW = tokenWindowList.size();
1099                if (NW > 0) {
1100                    pos = tokenWindowList.get(NW-1);
1101                    break;
1102                }
1103            }
1104            if (tokenNdx >= 0) {
1105                // found
1106                break;
1107            }
1108        }
1109
1110        if (pos != null) {
1111            // Move in front of any windows attached to this
1112            // one.
1113            WindowToken atoken = mTokenMap.get(pos.mClient.asBinder());
1114            if (atoken != null) {
1115                final int NC = atoken.windows.size();
1116                if (NC > 0) {
1117                    WindowState top = atoken.windows.get(NC-1);
1118                    if (top.mSubLayer >= 0) {
1119                        pos = top;
1120                    }
1121                }
1122            }
1123            placeWindowAfter(pos, win);
1124            return tokenWindowsPos;
1125        }
1126
1127        // Just search for the start of this layer.
1128        final int myLayer = win.mBaseLayer;
1129        int i;
1130        for (i = 0; i < N; i++) {
1131            WindowState w = windows.get(i);
1132            if (w.mBaseLayer > myLayer) {
1133                break;
1134            }
1135        }
1136        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1137                "Based on layer: Adding window " + win + " at " + i + " of " + N);
1138        windows.add(i, win);
1139        mWindowsChanged = true;
1140        return tokenWindowsPos;
1141    }
1142
1143    private void addFreeWindowToListLocked(final WindowState win) {
1144        final WindowList windows = win.getWindowList();
1145
1146        // Figure out where window should go, based on layer.
1147        final int myLayer = win.mBaseLayer;
1148        int i;
1149        for (i = windows.size() - 1; i >= 0; i--) {
1150            if (windows.get(i).mBaseLayer <= myLayer) {
1151                break;
1152            }
1153        }
1154        i++;
1155        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
1156                "Free window: Adding window " + win + " at " + i + " of " + windows.size());
1157        windows.add(i, win);
1158        mWindowsChanged = true;
1159    }
1160
1161    private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
1162        final WindowToken token = win.mToken;
1163        final DisplayContent displayContent = win.getDisplayContent();
1164        if (displayContent == null) {
1165            return;
1166        }
1167        final WindowState attached = win.mAttachedWindow;
1168
1169        WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
1170
1171        // Figure out this window's ordering relative to the window
1172        // it is attached to.
1173        final int NA = tokenWindowList.size();
1174        final int sublayer = win.mSubLayer;
1175        int largestSublayer = Integer.MIN_VALUE;
1176        WindowState windowWithLargestSublayer = null;
1177        int i;
1178        for (i = 0; i < NA; i++) {
1179            WindowState w = tokenWindowList.get(i);
1180            final int wSublayer = w.mSubLayer;
1181            if (wSublayer >= largestSublayer) {
1182                largestSublayer = wSublayer;
1183                windowWithLargestSublayer = w;
1184            }
1185            if (sublayer < 0) {
1186                // For negative sublayers, we go below all windows
1187                // in the same sublayer.
1188                if (wSublayer >= sublayer) {
1189                    if (addToToken) {
1190                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1191                        token.windows.add(i, win);
1192                    }
1193                    placeWindowBefore(wSublayer >= 0 ? attached : w, win);
1194                    break;
1195                }
1196            } else {
1197                // For positive sublayers, we go above all windows
1198                // in the same sublayer.
1199                if (wSublayer > sublayer) {
1200                    if (addToToken) {
1201                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1202                        token.windows.add(i, win);
1203                    }
1204                    placeWindowBefore(w, win);
1205                    break;
1206                }
1207            }
1208        }
1209        if (i >= NA) {
1210            if (addToToken) {
1211                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1212                token.windows.add(win);
1213            }
1214            if (sublayer < 0) {
1215                placeWindowBefore(attached, win);
1216            } else {
1217                placeWindowAfter(largestSublayer >= 0
1218                                 ? windowWithLargestSublayer
1219                                 : attached,
1220                                 win);
1221            }
1222        }
1223    }
1224
1225    private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
1226        if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
1227                " Callers=" + Debug.getCallers(4));
1228        if (win.mAttachedWindow == null) {
1229            final WindowToken token = win.mToken;
1230            int tokenWindowsPos = 0;
1231            if (token.appWindowToken != null) {
1232                tokenWindowsPos = addAppWindowToListLocked(win);
1233            } else {
1234                addFreeWindowToListLocked(win);
1235            }
1236            if (addToToken) {
1237                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
1238                token.windows.add(tokenWindowsPos, win);
1239            }
1240        } else {
1241            addAttachedWindowToListLocked(win, addToToken);
1242        }
1243
1244        if (win.mAppToken != null && addToToken) {
1245            win.mAppToken.allAppWindows.add(win);
1246        }
1247    }
1248
1249    static boolean canBeImeTarget(WindowState w) {
1250        final int fl = w.mAttrs.flags
1251                & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1252        if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)
1253                || w.mAttrs.type == TYPE_APPLICATION_STARTING) {
1254            if (DEBUG_INPUT_METHOD) {
1255                Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1256                if (!w.isVisibleOrAdding()) {
1257                    Slog.i(TAG, "  mSurface=" + w.mWinAnimator.mSurfaceControl
1258                            + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1259                            + " policyVis=" + w.mPolicyVisibility
1260                            + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1261                            + " attachHid=" + w.mAttachedHidden
1262                            + " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
1263                    if (w.mAppToken != null) {
1264                        Slog.i(TAG, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1265                    }
1266                }
1267            }
1268            return w.isVisibleOrAdding();
1269        }
1270        return false;
1271    }
1272
1273    /**
1274     * Dig through the WindowStates and find the one that the Input Method will target.
1275     * @param willMove
1276     * @return The index+1 in mWindows of the discovered target.
1277     */
1278    int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
1279        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1280        // same display. Or even when the current IME/target are not on the same screen as the next
1281        // IME/target. For now only look for input windows on the main screen.
1282        WindowList windows = getDefaultWindowListLocked();
1283        WindowState w = null;
1284        int i;
1285        for (i = windows.size() - 1; i >= 0; --i) {
1286            WindowState win = windows.get(i);
1287
1288            if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
1289                    + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1290            if (canBeImeTarget(win)) {
1291                w = win;
1292                //Slog.i(TAG, "Putting input method here!");
1293
1294                // Yet more tricksyness!  If this window is a "starting"
1295                // window, we do actually want to be on top of it, but
1296                // it is not -really- where input will go.  So if the caller
1297                // is not actually looking to move the IME, look down below
1298                // for a real window to target...
1299                if (!willMove
1300                        && w.mAttrs.type == TYPE_APPLICATION_STARTING
1301                        && i > 0) {
1302                    WindowState wb = windows.get(i-1);
1303                    if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1304                        i--;
1305                        w = wb;
1306                    }
1307                }
1308                break;
1309            }
1310        }
1311
1312        // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1313
1314        if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
1315
1316        // Now, a special case -- if the last target's window is in the
1317        // process of exiting, and is above the new target, keep on the
1318        // last target to avoid flicker.  Consider for example a Dialog with
1319        // the IME shown: when the Dialog is dismissed, we want to keep
1320        // the IME above it until it is completely gone so it doesn't drop
1321        // behind the dialog or its full-screen scrim.
1322        final WindowState curTarget = mInputMethodTarget;
1323        if (curTarget != null
1324                && curTarget.isDisplayedLw()
1325                && curTarget.isClosing()
1326                && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1327            if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
1328            return windows.indexOf(curTarget) + 1;
1329        }
1330
1331        if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
1332                + w + " willMove=" + willMove);
1333
1334        if (willMove && w != null) {
1335            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1336            if (token != null) {
1337
1338                // Now some fun for dealing with window animations that
1339                // modify the Z order.  We need to look at all windows below
1340                // the current target that are in this app, finding the highest
1341                // visible one in layering.
1342                WindowState highestTarget = null;
1343                int highestPos = 0;
1344                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1345                    WindowList curWindows = curTarget.getWindowList();
1346                    int pos = curWindows.indexOf(curTarget);
1347                    while (pos >= 0) {
1348                        WindowState win = curWindows.get(pos);
1349                        if (win.mAppToken != token) {
1350                            break;
1351                        }
1352                        if (!win.mRemoved) {
1353                            if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1354                                    highestTarget.mWinAnimator.mAnimLayer) {
1355                                highestTarget = win;
1356                                highestPos = pos;
1357                            }
1358                        }
1359                        pos--;
1360                    }
1361                }
1362
1363                if (highestTarget != null) {
1364                    if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
1365                            + " animating=" + highestTarget.mWinAnimator.isAnimating()
1366                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1367                            + " new layer=" + w.mWinAnimator.mAnimLayer);
1368
1369                    if (mAppTransition.isTransitionSet()) {
1370                        // If we are currently setting up for an animation,
1371                        // hold everything until we can find out what will happen.
1372                        mInputMethodTargetWaitingAnim = true;
1373                        mInputMethodTarget = highestTarget;
1374                        return highestPos + 1;
1375                    } else if (highestTarget.mWinAnimator.isAnimating() &&
1376                            highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1377                        // If the window we are currently targeting is involved
1378                        // with an animation, and it is on top of the next target
1379                        // we will be over, then hold off on moving until
1380                        // that is done.
1381                        mInputMethodTargetWaitingAnim = true;
1382                        mInputMethodTarget = highestTarget;
1383                        return highestPos + 1;
1384                    }
1385                }
1386            }
1387        }
1388
1389        //Slog.i(TAG, "Placing input method @" + (i+1));
1390        if (w != null) {
1391            if (willMove) {
1392                if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
1393                        + w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1394                mInputMethodTarget = w;
1395                mInputMethodTargetWaitingAnim = false;
1396                if (w.mAppToken != null) {
1397                    setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
1398                } else {
1399                    setInputMethodAnimLayerAdjustment(0);
1400                }
1401            }
1402            return i+1;
1403        }
1404        if (willMove) {
1405            if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
1406                    + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
1407            mInputMethodTarget = null;
1408            setInputMethodAnimLayerAdjustment(0);
1409        }
1410        return -1;
1411    }
1412
1413    void addInputMethodWindowToListLocked(WindowState win) {
1414        int pos = findDesiredInputMethodWindowIndexLocked(true);
1415        if (pos >= 0) {
1416            win.mTargetAppToken = mInputMethodTarget.mAppToken;
1417            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
1418                    TAG, "Adding input method window " + win + " at " + pos);
1419            // TODO(multidisplay): IMEs are only supported on the default display.
1420            getDefaultWindowListLocked().add(pos, win);
1421            mWindowsChanged = true;
1422            moveInputMethodDialogsLocked(pos+1);
1423            return;
1424        }
1425        win.mTargetAppToken = null;
1426        addWindowToListInOrderLocked(win, true);
1427        moveInputMethodDialogsLocked(pos);
1428    }
1429
1430    void setInputMethodAnimLayerAdjustment(int adj) {
1431        if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
1432        mInputMethodAnimLayerAdjustment = adj;
1433        WindowState imw = mInputMethodWindow;
1434        if (imw != null) {
1435            imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1436            if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1437                    + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1438            int wi = imw.mChildWindows.size();
1439            while (wi > 0) {
1440                wi--;
1441                WindowState cw = imw.mChildWindows.get(wi);
1442                cw.mWinAnimator.mAnimLayer = cw.mLayer + adj;
1443                if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
1444                        + " anim layer: " + cw.mWinAnimator.mAnimLayer);
1445            }
1446        }
1447        int di = mInputMethodDialogs.size();
1448        while (di > 0) {
1449            di --;
1450            imw = mInputMethodDialogs.get(di);
1451            imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
1452            if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
1453                    + " anim layer: " + imw.mWinAnimator.mAnimLayer);
1454        }
1455    }
1456
1457    private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1458        WindowList windows = win.getWindowList();
1459        int wpos = windows.indexOf(win);
1460        if (wpos >= 0) {
1461            if (wpos < interestingPos) interestingPos--;
1462            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
1463            windows.remove(wpos);
1464            mWindowsChanged = true;
1465            int NC = win.mChildWindows.size();
1466            while (NC > 0) {
1467                NC--;
1468                WindowState cw = win.mChildWindows.get(NC);
1469                int cpos = windows.indexOf(cw);
1470                if (cpos >= 0) {
1471                    if (cpos < interestingPos) interestingPos--;
1472                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
1473                            + cpos + ": " + cw);
1474                    windows.remove(cpos);
1475                }
1476            }
1477        }
1478        return interestingPos;
1479    }
1480
1481    private void reAddWindowToListInOrderLocked(WindowState win) {
1482        addWindowToListInOrderLocked(win, false);
1483        // This is a hack to get all of the child windows added as well
1484        // at the right position.  Child windows should be rare and
1485        // this case should be rare, so it shouldn't be that big a deal.
1486        WindowList windows = win.getWindowList();
1487        int wpos = windows.indexOf(win);
1488        if (wpos >= 0) {
1489            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos + ": " + win);
1490            windows.remove(wpos);
1491            mWindowsChanged = true;
1492            reAddWindowLocked(wpos, win);
1493        }
1494    }
1495
1496    void logWindowList(final WindowList windows, String prefix) {
1497        int N = windows.size();
1498        while (N > 0) {
1499            N--;
1500            Slog.v(TAG, prefix + "#" + N + ": " + windows.get(N));
1501        }
1502    }
1503
1504    void moveInputMethodDialogsLocked(int pos) {
1505        ArrayList<WindowState> dialogs = mInputMethodDialogs;
1506
1507        // TODO(multidisplay): IMEs are only supported on the default display.
1508        WindowList windows = getDefaultWindowListLocked();
1509        final int N = dialogs.size();
1510        if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1511        for (int i=0; i<N; i++) {
1512            pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1513        }
1514        if (DEBUG_INPUT_METHOD) {
1515            Slog.v(TAG, "Window list w/pos=" + pos);
1516            logWindowList(windows, "  ");
1517        }
1518
1519        if (pos >= 0) {
1520            final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1521            // Skip windows owned by the input method.
1522            if (mInputMethodWindow != null) {
1523                while (pos < windows.size()) {
1524                    WindowState wp = windows.get(pos);
1525                    if (wp == mInputMethodWindow || wp.mAttachedWindow == mInputMethodWindow) {
1526                        pos++;
1527                        continue;
1528                    }
1529                    break;
1530                }
1531            }
1532            if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1533            for (int i=0; i<N; i++) {
1534                WindowState win = dialogs.get(i);
1535                win.mTargetAppToken = targetAppToken;
1536                pos = reAddWindowLocked(pos, win);
1537            }
1538            if (DEBUG_INPUT_METHOD) {
1539                Slog.v(TAG, "Final window list:");
1540                logWindowList(windows, "  ");
1541            }
1542            return;
1543        }
1544        for (int i=0; i<N; i++) {
1545            WindowState win = dialogs.get(i);
1546            win.mTargetAppToken = null;
1547            reAddWindowToListInOrderLocked(win);
1548            if (DEBUG_INPUT_METHOD) {
1549                Slog.v(TAG, "No IM target, final list:");
1550                logWindowList(windows, "  ");
1551            }
1552        }
1553    }
1554
1555    boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1556        final WindowState imWin = mInputMethodWindow;
1557        final int DN = mInputMethodDialogs.size();
1558        if (imWin == null && DN == 0) {
1559            return false;
1560        }
1561
1562        // TODO(multidisplay): IMEs are only supported on the default display.
1563        WindowList windows = getDefaultWindowListLocked();
1564
1565        int imPos = findDesiredInputMethodWindowIndexLocked(true);
1566        if (imPos >= 0) {
1567            // In this case, the input method windows are to be placed
1568            // immediately above the window they are targeting.
1569
1570            // First check to see if the input method windows are already
1571            // located here, and contiguous.
1572            final int N = windows.size();
1573            WindowState firstImWin = imPos < N
1574                    ? windows.get(imPos) : null;
1575
1576            // Figure out the actual input method window that should be
1577            // at the bottom of their stack.
1578            WindowState baseImWin = imWin != null
1579                    ? imWin : mInputMethodDialogs.get(0);
1580            if (baseImWin.mChildWindows.size() > 0) {
1581                WindowState cw = baseImWin.mChildWindows.get(0);
1582                if (cw.mSubLayer < 0) baseImWin = cw;
1583            }
1584
1585            if (firstImWin == baseImWin) {
1586                // The windows haven't moved...  but are they still contiguous?
1587                // First find the top IM window.
1588                int pos = imPos+1;
1589                while (pos < N) {
1590                    if (!(windows.get(pos)).mIsImWindow) {
1591                        break;
1592                    }
1593                    pos++;
1594                }
1595                pos++;
1596                // Now there should be no more input method windows above.
1597                while (pos < N) {
1598                    if ((windows.get(pos)).mIsImWindow) {
1599                        break;
1600                    }
1601                    pos++;
1602                }
1603                if (pos >= N) {
1604                    // Z order is good.
1605                    // The IM target window may be changed, so update the mTargetAppToken.
1606                    if (imWin != null) {
1607                        imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1608                    }
1609                    return false;
1610                }
1611            }
1612
1613            if (imWin != null) {
1614                if (DEBUG_INPUT_METHOD) {
1615                    Slog.v(TAG, "Moving IM from " + imPos);
1616                    logWindowList(windows, "  ");
1617                }
1618                imPos = tmpRemoveWindowLocked(imPos, imWin);
1619                if (DEBUG_INPUT_METHOD) {
1620                    Slog.v(TAG, "List after removing with new pos " + imPos + ":");
1621                    logWindowList(windows, "  ");
1622                }
1623                imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1624                reAddWindowLocked(imPos, imWin);
1625                if (DEBUG_INPUT_METHOD) {
1626                    Slog.v(TAG, "List after moving IM to " + imPos + ":");
1627                    logWindowList(windows, "  ");
1628                }
1629                if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1630            } else {
1631                moveInputMethodDialogsLocked(imPos);
1632            }
1633
1634        } else {
1635            // In this case, the input method windows go in a fixed layer,
1636            // because they aren't currently associated with a focus window.
1637
1638            if (imWin != null) {
1639                if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
1640                tmpRemoveWindowLocked(0, imWin);
1641                imWin.mTargetAppToken = null;
1642                reAddWindowToListInOrderLocked(imWin);
1643                if (DEBUG_INPUT_METHOD) {
1644                    Slog.v(TAG, "List with no IM target:");
1645                    logWindowList(windows, "  ");
1646                }
1647                if (DN > 0) moveInputMethodDialogsLocked(-1);
1648            } else {
1649                moveInputMethodDialogsLocked(-1);
1650            }
1651
1652        }
1653
1654        if (needAssignLayers) {
1655            assignLayersLocked(windows);
1656        }
1657
1658        return true;
1659    }
1660
1661    final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1662        if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
1663                + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1664                + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1665                        ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
1666                + " upper=" + mUpperWallpaperTarget
1667                + " lower=" + mLowerWallpaperTarget);
1668        return (wallpaperTarget != null
1669                        && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1670                                && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
1671                || mUpperWallpaperTarget != null
1672                || mLowerWallpaperTarget != null;
1673    }
1674
1675    static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1676    static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1677
1678    int adjustWallpaperWindowsLocked() {
1679        mInnerFields.mWallpaperMayChange = false;
1680        boolean targetChanged = false;
1681
1682        // TODO(multidisplay): Wallpapers on main screen only.
1683        final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
1684        final int dw = displayInfo.logicalWidth;
1685        final int dh = displayInfo.logicalHeight;
1686
1687        // First find top-most window that has asked to be on top of the
1688        // wallpaper; all wallpapers go behind it.
1689        final WindowList windows = getDefaultWindowListLocked();
1690        int N = windows.size();
1691        WindowState w = null;
1692        WindowState foundW = null;
1693        int foundI = 0;
1694        WindowState topCurW = null;
1695        int topCurI = 0;
1696        int windowDetachedI = -1;
1697        int i = N;
1698        while (i > 0) {
1699            i--;
1700            w = windows.get(i);
1701            if ((w.mAttrs.type == TYPE_WALLPAPER)) {
1702                if (topCurW == null) {
1703                    topCurW = w;
1704                    topCurI = i;
1705                }
1706                continue;
1707            }
1708            topCurW = null;
1709            if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
1710                // If this window's app token is hidden and not animating,
1711                // it is of no interest to us.
1712                if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
1713                    if (DEBUG_WALLPAPER) Slog.v(TAG,
1714                            "Skipping hidden and not animating token: " + w);
1715                    continue;
1716                }
1717            }
1718            if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
1719                    + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
1720
1721            // If the app is executing an animation because the keyguard is going away, keep the
1722            // wallpaper during the animation so it doesn't flicker out.
1723            final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
1724                    || (w.mAppToken != null
1725                            && w.mWinAnimator.keyguardGoingAwayAnimation);
1726            if (hasWallpaper && w.isOnScreen()
1727                    && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
1728                if (DEBUG_WALLPAPER) Slog.v(TAG,
1729                        "Found wallpaper target: #" + i + "=" + w);
1730                foundW = w;
1731                foundI = i;
1732                if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
1733                    // The current wallpaper target is animating, so we'll
1734                    // look behind it for another possible target and figure
1735                    // out what is going on below.
1736                    if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
1737                            + ": token animating, looking behind.");
1738                    continue;
1739                }
1740                break;
1741            } else if (w == mAnimator.mWindowDetachedWallpaper) {
1742                windowDetachedI = i;
1743            }
1744        }
1745
1746        if (foundW == null && windowDetachedI >= 0) {
1747            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
1748                    "Found animating detached wallpaper activity: #" + i + "=" + w);
1749            foundW = w;
1750            foundI = windowDetachedI;
1751        }
1752
1753        if (mWallpaperTarget != foundW
1754                && (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) {
1755            if (DEBUG_WALLPAPER_LIGHT) {
1756                Slog.v(TAG, "New wallpaper target: " + foundW
1757                        + " oldTarget: " + mWallpaperTarget);
1758            }
1759
1760            mLowerWallpaperTarget = null;
1761            mUpperWallpaperTarget = null;
1762
1763            WindowState oldW = mWallpaperTarget;
1764            mWallpaperTarget = foundW;
1765            targetChanged = true;
1766
1767            // Now what is happening...  if the current and new targets are
1768            // animating, then we are in our super special mode!
1769            if (foundW != null && oldW != null) {
1770                boolean oldAnim = oldW.isAnimatingLw();
1771                boolean foundAnim = foundW.isAnimatingLw();
1772                if (DEBUG_WALLPAPER_LIGHT) {
1773                    Slog.v(TAG, "New animation: " + foundAnim
1774                            + " old animation: " + oldAnim);
1775                }
1776                if (foundAnim && oldAnim) {
1777                    int oldI = windows.indexOf(oldW);
1778                    if (DEBUG_WALLPAPER_LIGHT) {
1779                        Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
1780                    }
1781                    if (oldI >= 0) {
1782                        if (DEBUG_WALLPAPER_LIGHT) {
1783                            Slog.v(TAG, "Animating wallpapers: old#" + oldI
1784                                    + "=" + oldW + "; new#" + foundI
1785                                    + "=" + foundW);
1786                        }
1787
1788                        // Set the new target correctly.
1789                        if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
1790                            if (DEBUG_WALLPAPER_LIGHT) {
1791                                Slog.v(TAG, "Old wallpaper still the target.");
1792                            }
1793                            mWallpaperTarget = oldW;
1794                            foundW = oldW;
1795                            foundI = oldI;
1796                        }
1797                        // Now set the upper and lower wallpaper targets
1798                        // correctly, and make sure that we are positioning
1799                        // the wallpaper below the lower.
1800                        else if (foundI > oldI) {
1801                            // The new target is on top of the old one.
1802                            if (DEBUG_WALLPAPER_LIGHT) {
1803                                Slog.v(TAG, "Found target above old target.");
1804                            }
1805                            mUpperWallpaperTarget = foundW;
1806                            mLowerWallpaperTarget = oldW;
1807                            foundW = oldW;
1808                            foundI = oldI;
1809                        } else {
1810                            // The new target is below the old one.
1811                            if (DEBUG_WALLPAPER_LIGHT) {
1812                                Slog.v(TAG, "Found target below old target.");
1813                            }
1814                            mUpperWallpaperTarget = oldW;
1815                            mLowerWallpaperTarget = foundW;
1816                        }
1817                    }
1818                }
1819            }
1820
1821        } else if (mLowerWallpaperTarget != null) {
1822            // Is it time to stop animating?
1823            if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
1824                if (DEBUG_WALLPAPER_LIGHT) {
1825                    Slog.v(TAG, "No longer animating wallpaper targets!");
1826                }
1827                mLowerWallpaperTarget = null;
1828                mUpperWallpaperTarget = null;
1829                mWallpaperTarget = foundW;
1830                targetChanged = true;
1831            }
1832        }
1833
1834        boolean visible = foundW != null;
1835        if (visible) {
1836            // The window is visible to the compositor...  but is it visible
1837            // to the user?  That is what the wallpaper cares about.
1838            visible = isWallpaperVisible(foundW);
1839            if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
1840
1841            // If the wallpaper target is animating, we may need to copy
1842            // its layer adjustment.  Only do this if we are not transfering
1843            // between two wallpaper targets.
1844            mWallpaperAnimLayerAdjustment =
1845                    (mLowerWallpaperTarget == null && foundW.mAppToken != null)
1846                    ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
1847
1848            final int maxLayer = mPolicy.getMaxWallpaperLayer()
1849                    * TYPE_LAYER_MULTIPLIER
1850                    + TYPE_LAYER_OFFSET;
1851
1852            // Now w is the window we are supposed to be behind...  but we
1853            // need to be sure to also be behind any of its attached windows,
1854            // AND any starting window associated with it, AND below the
1855            // maximum layer the policy allows for wallpapers.
1856            while (foundI > 0) {
1857                WindowState wb = windows.get(foundI-1);
1858                if (wb.mBaseLayer < maxLayer &&
1859                        wb.mAttachedWindow != foundW &&
1860                        (foundW.mAttachedWindow == null ||
1861                                wb.mAttachedWindow != foundW.mAttachedWindow) &&
1862                        (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
1863                                foundW.mToken == null || wb.mToken != foundW.mToken)) {
1864                    // This window is not related to the previous one in any
1865                    // interesting way, so stop here.
1866                    break;
1867                }
1868                foundW = wb;
1869                foundI--;
1870            }
1871        } else {
1872            if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
1873        }
1874
1875        if (foundW == null && topCurW != null) {
1876            // There is no wallpaper target, so it goes at the bottom.
1877            // We will assume it is the same place as last time, if known.
1878            foundW = topCurW;
1879            foundI = topCurI+1;
1880        } else {
1881            // Okay i is the position immediately above the wallpaper.  Look at
1882            // what is below it for later.
1883            foundW = foundI > 0 ? windows.get(foundI-1) : null;
1884        }
1885
1886        if (visible) {
1887            if (mWallpaperTarget.mWallpaperX >= 0) {
1888                mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1889                mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
1890            }
1891            if (mWallpaperTarget.mWallpaperY >= 0) {
1892                mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1893                mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
1894            }
1895        }
1896
1897        // Start stepping backwards from here, ensuring that our wallpaper windows
1898        // are correctly placed.
1899        int changed = 0;
1900        int curTokenIndex = mWallpaperTokens.size();
1901        while (curTokenIndex > 0) {
1902            curTokenIndex--;
1903            WindowToken token = mWallpaperTokens.get(curTokenIndex);
1904            if (token.hidden == visible) {
1905                if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
1906                        "Wallpaper token " + token + " hidden=" + !visible);
1907                changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1908                token.hidden = !visible;
1909                // Need to do a layout to ensure the wallpaper now has the
1910                // correct size.
1911                getDefaultDisplayContentLocked().layoutNeeded = true;
1912            }
1913
1914            int curWallpaperIndex = token.windows.size();
1915            while (curWallpaperIndex > 0) {
1916                curWallpaperIndex--;
1917                WindowState wallpaper = token.windows.get(curWallpaperIndex);
1918
1919                if (visible) {
1920                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
1921                }
1922
1923                // First, make sure the client has the current visibility
1924                // state.
1925                dispatchWallpaperVisibility(wallpaper, visible);
1926
1927                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
1928                if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
1929                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
1930
1931                // First, if this window is at the current index, then all
1932                // is well.
1933                if (wallpaper == foundW) {
1934                    foundI--;
1935                    foundW = foundI > 0
1936                            ? windows.get(foundI-1) : null;
1937                    continue;
1938                }
1939
1940                // The window didn't match...  the current wallpaper window,
1941                // wherever it is, is in the wrong place, so make sure it is
1942                // not in the list.
1943                int oldIndex = windows.indexOf(wallpaper);
1944                if (oldIndex >= 0) {
1945                    if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
1946                            + oldIndex + ": " + wallpaper);
1947                    windows.remove(oldIndex);
1948                    mWindowsChanged = true;
1949                    if (oldIndex < foundI) {
1950                        foundI--;
1951                    }
1952                }
1953
1954                // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
1955                // layer. For keyguard over wallpaper put the wallpaper under the keyguard.
1956                int insertionIndex = 0;
1957                if (visible && foundW != null) {
1958                    final int type = foundW.mAttrs.type;
1959                    final int privateFlags = foundW.mAttrs.privateFlags;
1960                    if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
1961                            || type == TYPE_KEYGUARD_SCRIM) {
1962                        insertionIndex = windows.indexOf(foundW);
1963                    }
1964                }
1965                if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
1966                    Slog.v(TAG, "Moving wallpaper " + wallpaper
1967                            + " from " + oldIndex + " to " + insertionIndex);
1968                }
1969
1970                windows.add(insertionIndex, wallpaper);
1971                mWindowsChanged = true;
1972                changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
1973            }
1974        }
1975
1976        /*
1977        final TaskStack targetStack =
1978                mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
1979        if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
1980                targetStack != null && !targetStack.isHomeStack()) {
1981            // If the wallpaper target is not on the home stack then make sure that all windows
1982            // from other non-home stacks are above the wallpaper.
1983            for (i = foundI - 1; i >= 0; --i) {
1984                WindowState win = windows.get(i);
1985                if (!win.isVisibleLw()) {
1986                    continue;
1987                }
1988                final TaskStack winStack = win.getStack();
1989                if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
1990                    windows.remove(i);
1991                    windows.add(foundI + 1, win);
1992                }
1993            }
1994        }
1995        */
1996
1997        if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
1998            Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
1999                    + " lower=" + mLowerWallpaperTarget + " upper="
2000                    + mUpperWallpaperTarget);
2001        }
2002
2003        return changed;
2004    }
2005
2006    void setWallpaperAnimLayerAdjustmentLocked(int adj) {
2007        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
2008                "Setting wallpaper layer adj to " + adj);
2009        mWallpaperAnimLayerAdjustment = adj;
2010        int curTokenIndex = mWallpaperTokens.size();
2011        while (curTokenIndex > 0) {
2012            curTokenIndex--;
2013            WindowToken token = mWallpaperTokens.get(curTokenIndex);
2014            int curWallpaperIndex = token.windows.size();
2015            while (curWallpaperIndex > 0) {
2016                curWallpaperIndex--;
2017                WindowState wallpaper = token.windows.get(curWallpaperIndex);
2018                wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
2019                if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
2020                        + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
2021            }
2022        }
2023    }
2024
2025    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
2026            boolean sync) {
2027        boolean changed = false;
2028        boolean rawChanged = false;
2029        float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
2030        float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
2031        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
2032        int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
2033        changed = wallpaperWin.mXOffset != offset;
2034        if (changed) {
2035            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
2036                    + wallpaperWin + " x: " + offset);
2037            wallpaperWin.mXOffset = offset;
2038        }
2039        if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
2040            wallpaperWin.mWallpaperX = wpx;
2041            wallpaperWin.mWallpaperXStep = wpxs;
2042            rawChanged = true;
2043        }
2044
2045        float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
2046        float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
2047        int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
2048        offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
2049        if (wallpaperWin.mYOffset != offset) {
2050            if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
2051                    + wallpaperWin + " y: " + offset);
2052            changed = true;
2053            wallpaperWin.mYOffset = offset;
2054        }
2055        if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
2056            wallpaperWin.mWallpaperY = wpy;
2057            wallpaperWin.mWallpaperYStep = wpys;
2058            rawChanged = true;
2059        }
2060
2061        if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
2062                    WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
2063            try {
2064                if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
2065                        + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
2066                        + " y=" + wallpaperWin.mWallpaperY);
2067                if (sync) {
2068                    mWaitingOnWallpaper = wallpaperWin;
2069                }
2070                wallpaperWin.mClient.dispatchWallpaperOffsets(
2071                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
2072                        wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
2073                if (sync) {
2074                    if (mWaitingOnWallpaper != null) {
2075                        long start = SystemClock.uptimeMillis();
2076                        if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
2077                                < start) {
2078                            try {
2079                                if (DEBUG_WALLPAPER) Slog.v(TAG,
2080                                        "Waiting for offset complete...");
2081                                mWindowMap.wait(WALLPAPER_TIMEOUT);
2082                            } catch (InterruptedException e) {
2083                            }
2084                            if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
2085                            if ((start+WALLPAPER_TIMEOUT)
2086                                    < SystemClock.uptimeMillis()) {
2087                                Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
2088                                        + wallpaperWin);
2089                                mLastWallpaperTimeoutTime = start;
2090                            }
2091                        }
2092                        mWaitingOnWallpaper = null;
2093                    }
2094                }
2095            } catch (RemoteException e) {
2096            }
2097        }
2098
2099        return changed;
2100    }
2101
2102    void wallpaperOffsetsComplete(IBinder window) {
2103        synchronized (mWindowMap) {
2104            if (mWaitingOnWallpaper != null &&
2105                    mWaitingOnWallpaper.mClient.asBinder() == window) {
2106                mWaitingOnWallpaper = null;
2107                mWindowMap.notifyAll();
2108            }
2109        }
2110    }
2111
2112    void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
2113        final DisplayContent displayContent = changingTarget.getDisplayContent();
2114        if (displayContent == null) {
2115            return;
2116        }
2117        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2118        final int dw = displayInfo.logicalWidth;
2119        final int dh = displayInfo.logicalHeight;
2120
2121        WindowState target = mWallpaperTarget;
2122        if (target != null) {
2123            if (target.mWallpaperX >= 0) {
2124                mLastWallpaperX = target.mWallpaperX;
2125            } else if (changingTarget.mWallpaperX >= 0) {
2126                mLastWallpaperX = changingTarget.mWallpaperX;
2127            }
2128            if (target.mWallpaperY >= 0) {
2129                mLastWallpaperY = target.mWallpaperY;
2130            } else if (changingTarget.mWallpaperY >= 0) {
2131                mLastWallpaperY = changingTarget.mWallpaperY;
2132            }
2133        }
2134
2135        int curTokenIndex = mWallpaperTokens.size();
2136        while (curTokenIndex > 0) {
2137            curTokenIndex--;
2138            WindowToken token = mWallpaperTokens.get(curTokenIndex);
2139            int curWallpaperIndex = token.windows.size();
2140            while (curWallpaperIndex > 0) {
2141                curWallpaperIndex--;
2142                WindowState wallpaper = token.windows.get(curWallpaperIndex);
2143                if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
2144                    WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
2145                    winAnimator.computeShownFrameLocked();
2146                    // No need to lay out the windows - we can just set the wallpaper position
2147                    // directly.
2148                    winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
2149                    // We only want to be synchronous with one wallpaper.
2150                    sync = false;
2151                }
2152            }
2153        }
2154    }
2155
2156    /**
2157     * Check wallpaper for visiblity change and notify window if so.
2158     * @param wallpaper The wallpaper to test and notify.
2159     * @param visible Current visibility.
2160     */
2161    void dispatchWallpaperVisibility(final WindowState wallpaper, final boolean visible) {
2162        if (wallpaper.mWallpaperVisible != visible) {
2163            wallpaper.mWallpaperVisible = visible;
2164            try {
2165                if (DEBUG_VISIBILITY || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2166                        "Updating vis of wallpaper " + wallpaper
2167                        + ": " + visible + " from:\n" + Debug.getCallers(4, "  "));
2168                wallpaper.mClient.dispatchAppVisibility(visible);
2169            } catch (RemoteException e) {
2170            }
2171        }
2172    }
2173
2174    void updateWallpaperVisibilityLocked() {
2175        final boolean visible = isWallpaperVisible(mWallpaperTarget);
2176        final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
2177        if (displayContent == null) {
2178            return;
2179        }
2180        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2181        final int dw = displayInfo.logicalWidth;
2182        final int dh = displayInfo.logicalHeight;
2183
2184        int curTokenIndex = mWallpaperTokens.size();
2185        while (curTokenIndex > 0) {
2186            curTokenIndex--;
2187            WindowToken token = mWallpaperTokens.get(curTokenIndex);
2188            if (token.hidden == visible) {
2189                token.hidden = !visible;
2190                // Need to do a layout to ensure the wallpaper now has the
2191                // correct size.
2192                getDefaultDisplayContentLocked().layoutNeeded = true;
2193            }
2194
2195            int curWallpaperIndex = token.windows.size();
2196            while (curWallpaperIndex > 0) {
2197                curWallpaperIndex--;
2198                WindowState wallpaper = token.windows.get(curWallpaperIndex);
2199                if (visible) {
2200                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
2201                }
2202
2203                dispatchWallpaperVisibility(wallpaper, visible);
2204            }
2205        }
2206    }
2207
2208    public int addWindow(Session session, IWindow client, int seq,
2209            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
2210            Rect outContentInsets, InputChannel outInputChannel) {
2211        int[] appOp = new int[1];
2212        int res = mPolicy.checkAddPermission(attrs, appOp);
2213        if (res != WindowManagerGlobal.ADD_OKAY) {
2214            return res;
2215        }
2216
2217        boolean reportNewConfig = false;
2218        WindowState attachedWindow = null;
2219        WindowState win = null;
2220        long origId;
2221        final int type = attrs.type;
2222
2223        synchronized(mWindowMap) {
2224            if (!mDisplayReady) {
2225                throw new IllegalStateException("Display has not been initialialized");
2226            }
2227
2228            final DisplayContent displayContent = getDisplayContentLocked(displayId);
2229            if (displayContent == null) {
2230                Slog.w(TAG, "Attempted to add window to a display that does not exist: "
2231                        + displayId + ".  Aborting.");
2232                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2233            }
2234            if (!displayContent.hasAccess(session.mUid)) {
2235                Slog.w(TAG, "Attempted to add window to a display for which the application "
2236                        + "does not have access: " + displayId + ".  Aborting.");
2237                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2238            }
2239
2240            if (mWindowMap.containsKey(client.asBinder())) {
2241                Slog.w(TAG, "Window " + client + " is already added");
2242                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
2243            }
2244
2245            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
2246                attachedWindow = windowForClientLocked(null, attrs.token, false);
2247                if (attachedWindow == null) {
2248                    Slog.w(TAG, "Attempted to add window with token that is not a window: "
2249                          + attrs.token + ".  Aborting.");
2250                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2251                }
2252                if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
2253                        && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
2254                    Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
2255                            + attrs.token + ".  Aborting.");
2256                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
2257                }
2258            }
2259
2260            if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
2261                Slog.w(TAG, "Attempted to add private presentation window to a non-private display.  Aborting.");
2262                return WindowManagerGlobal.ADD_PERMISSION_DENIED;
2263            }
2264
2265            boolean addToken = false;
2266            WindowToken token = mTokenMap.get(attrs.token);
2267            if (token == null) {
2268                if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2269                    Slog.w(TAG, "Attempted to add application window with unknown token "
2270                          + attrs.token + ".  Aborting.");
2271                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2272                }
2273                if (type == TYPE_INPUT_METHOD) {
2274                    Slog.w(TAG, "Attempted to add input method window with unknown token "
2275                          + attrs.token + ".  Aborting.");
2276                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2277                }
2278                if (type == TYPE_VOICE_INTERACTION) {
2279                    Slog.w(TAG, "Attempted to add voice interaction window with unknown token "
2280                          + attrs.token + ".  Aborting.");
2281                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2282                }
2283                if (type == TYPE_WALLPAPER) {
2284                    Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
2285                          + attrs.token + ".  Aborting.");
2286                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2287                }
2288                if (type == TYPE_DREAM) {
2289                    Slog.w(TAG, "Attempted to add Dream window with unknown token "
2290                          + attrs.token + ".  Aborting.");
2291                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2292                }
2293                token = new WindowToken(this, attrs.token, -1, false);
2294                addToken = true;
2295            } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
2296                AppWindowToken atoken = token.appWindowToken;
2297                if (atoken == null) {
2298                    Slog.w(TAG, "Attempted to add window with non-application token "
2299                          + token + ".  Aborting.");
2300                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
2301                } else if (atoken.removed) {
2302                    Slog.w(TAG, "Attempted to add window with exiting application token "
2303                          + token + ".  Aborting.");
2304                    return WindowManagerGlobal.ADD_APP_EXITING;
2305                }
2306                if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
2307                    // No need for this guy!
2308                    if (localLOGV) Slog.v(
2309                            TAG, "**** NO NEED TO START: " + attrs.getTitle());
2310                    return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
2311                }
2312            } else if (type == TYPE_INPUT_METHOD) {
2313                if (token.windowType != TYPE_INPUT_METHOD) {
2314                    Slog.w(TAG, "Attempted to add input method window with bad token "
2315                            + attrs.token + ".  Aborting.");
2316                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2317                }
2318            } else if (type == TYPE_VOICE_INTERACTION) {
2319                if (token.windowType != TYPE_VOICE_INTERACTION) {
2320                    Slog.w(TAG, "Attempted to add voice interaction window with bad token "
2321                            + attrs.token + ".  Aborting.");
2322                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2323                }
2324            } else if (type == TYPE_WALLPAPER) {
2325                if (token.windowType != TYPE_WALLPAPER) {
2326                    Slog.w(TAG, "Attempted to add wallpaper window with bad token "
2327                            + attrs.token + ".  Aborting.");
2328                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2329                }
2330            } else if (type == TYPE_DREAM) {
2331                if (token.windowType != TYPE_DREAM) {
2332                    Slog.w(TAG, "Attempted to add Dream window with bad token "
2333                            + attrs.token + ".  Aborting.");
2334                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
2335                }
2336            } else if (token.appWindowToken != null) {
2337                Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
2338                // It is not valid to use an app token with other system types; we will
2339                // instead make a new token for it (as if null had been passed in for the token).
2340                attrs.token = null;
2341                token = new WindowToken(this, null, -1, false);
2342                addToken = true;
2343            }
2344
2345            win = new WindowState(this, session, client, token,
2346                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
2347            if (win.mDeathRecipient == null) {
2348                // Client has apparently died, so there is no reason to
2349                // continue.
2350                Slog.w(TAG, "Adding window client " + client.asBinder()
2351                        + " that is dead, aborting.");
2352                return WindowManagerGlobal.ADD_APP_EXITING;
2353            }
2354
2355            if (win.getDisplayContent() == null) {
2356                Slog.w(TAG, "Adding window to Display that has been removed.");
2357                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
2358            }
2359
2360            mPolicy.adjustWindowParamsLw(win.mAttrs);
2361            win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
2362
2363            res = mPolicy.prepareAddWindowLw(win, attrs);
2364            if (res != WindowManagerGlobal.ADD_OKAY) {
2365                return res;
2366            }
2367
2368            if (outInputChannel != null && (attrs.inputFeatures
2369                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
2370                String name = win.makeInputChannelName();
2371                InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2372                win.setInputChannel(inputChannels[0]);
2373                inputChannels[1].transferTo(outInputChannel);
2374
2375                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
2376            }
2377
2378            // From now on, no exceptions or errors allowed!
2379
2380            res = WindowManagerGlobal.ADD_OKAY;
2381
2382            origId = Binder.clearCallingIdentity();
2383
2384            if (addToken) {
2385                Slog.w("BadTokenDebug", "addWindow: Adding token=" + token + " attrs.token=" + attrs.token);
2386                mTokenMap.put(attrs.token, token);
2387            }
2388            win.attach();
2389            mWindowMap.put(client.asBinder(), win);
2390            if (win.mAppOp != AppOpsManager.OP_NONE) {
2391                if (mAppOps.startOpNoThrow(win.mAppOp, win.getOwningUid(), win.getOwningPackage())
2392                        != AppOpsManager.MODE_ALLOWED) {
2393                    win.setAppOpVisibilityLw(false);
2394                }
2395            }
2396
2397            if (type == TYPE_APPLICATION_STARTING && token.appWindowToken != null) {
2398                token.appWindowToken.startingWindow = win;
2399                if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
2400                        + " startingWindow=" + win);
2401            }
2402
2403            boolean imMayMove = true;
2404
2405            if (type == TYPE_INPUT_METHOD) {
2406                win.mGivenInsetsPending = true;
2407                mInputMethodWindow = win;
2408                addInputMethodWindowToListLocked(win);
2409                imMayMove = false;
2410            } else if (type == TYPE_INPUT_METHOD_DIALOG) {
2411                mInputMethodDialogs.add(win);
2412                addWindowToListInOrderLocked(win, true);
2413                moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
2414                imMayMove = false;
2415            } else {
2416                addWindowToListInOrderLocked(win, true);
2417                if (type == TYPE_WALLPAPER) {
2418                    mLastWallpaperTimeoutTime = 0;
2419                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2420                } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2421                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2422                } else if (mWallpaperTarget != null
2423                        && mWallpaperTarget.mLayer >= win.mBaseLayer) {
2424                    // If there is currently a wallpaper being shown, and
2425                    // the base layer of the new window is below the current
2426                    // layer of the target window, then adjust the wallpaper.
2427                    // This is to avoid a new window being placed between the
2428                    // wallpaper and its target.
2429                    displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2430                }
2431            }
2432
2433            win.mWinAnimator.mEnterAnimationPending = true;
2434
2435            if (displayContent.isDefaultDisplay) {
2436                mPolicy.getContentInsetHintLw(attrs, outContentInsets);
2437            } else {
2438                outContentInsets.setEmpty();
2439            }
2440
2441            if (mInTouchMode) {
2442                res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
2443            }
2444            if (win.mAppToken == null || !win.mAppToken.clientHidden) {
2445                res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
2446            }
2447
2448            mInputMonitor.setUpdateInputWindowsNeededLw();
2449
2450            boolean focusChanged = false;
2451            if (win.canReceiveKeys()) {
2452                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
2453                        false /*updateInputWindows*/);
2454                if (focusChanged) {
2455                    imMayMove = false;
2456                }
2457            }
2458
2459            if (imMayMove) {
2460                moveInputMethodWindowsIfNeededLocked(false);
2461            }
2462
2463            assignLayersLocked(displayContent.getWindowList());
2464            // Don't do layout here, the window must call
2465            // relayout to be displayed, so we'll do it there.
2466
2467            if (focusChanged) {
2468                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
2469            }
2470            mInputMonitor.updateInputWindowsLw(false /*force*/);
2471
2472            if (localLOGV) Slog.v(
2473                TAG, "New client " + client.asBinder()
2474                + ": window=" + win);
2475
2476            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
2477                reportNewConfig = true;
2478            }
2479        }
2480
2481        if (reportNewConfig) {
2482            sendNewConfiguration();
2483        }
2484
2485        Binder.restoreCallingIdentity(origId);
2486
2487        return res;
2488    }
2489
2490    /**
2491     * Returns whether screen capture is disabled for all windows of a specific user.
2492     */
2493    boolean isScreenCaptureDisabledLocked(int userId) {
2494        Boolean disabled = mScreenCaptureDisabled.get(userId);
2495        if (disabled == null) {
2496            return false;
2497        }
2498        return disabled;
2499    }
2500
2501    /**
2502     * Set mScreenCaptureDisabled for specific user
2503     */
2504    @Override
2505    public void setScreenCaptureDisabled(int userId, boolean disabled) {
2506        int callingUid = Binder.getCallingUid();
2507        if (callingUid != Process.SYSTEM_UID) {
2508            throw new SecurityException("Only system can call setScreenCaptureDisabled.");
2509        }
2510
2511        synchronized(mWindowMap) {
2512            mScreenCaptureDisabled.put(userId, disabled);
2513        }
2514    }
2515
2516    public void removeWindow(Session session, IWindow client) {
2517        synchronized(mWindowMap) {
2518            WindowState win = windowForClientLocked(session, client, false);
2519            if (win == null) {
2520                return;
2521            }
2522            removeWindowLocked(session, win);
2523        }
2524    }
2525
2526    public void removeWindowLocked(Session session, WindowState win) {
2527        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2528            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
2529        }
2530
2531        if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
2532                TAG, "Remove " + win + " client="
2533                + Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
2534                + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers="
2535                + Debug.getCallers(4));
2536
2537        final long origId = Binder.clearCallingIdentity();
2538
2539        win.disposeInputChannel();
2540
2541        if (DEBUG_APP_TRANSITIONS) Slog.v(
2542                TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
2543                + " mExiting=" + win.mExiting
2544                + " isAnimating=" + win.mWinAnimator.isAnimating()
2545                + " app-animation="
2546                + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
2547                + " inPendingTransaction="
2548                + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2549                + " mDisplayFrozen=" + mDisplayFrozen);
2550        // Visibility of the removed window. Will be used later to update orientation later on.
2551        boolean wasVisible = false;
2552        // First, see if we need to run an animation.  If we do, we have
2553        // to hold off on removing the window until the animation is done.
2554        // If the display is frozen, just remove immediately, since the
2555        // animation wouldn't be seen.
2556        if (win.mHasSurface && okToDisplay()) {
2557            // If we are not currently running the exit animation, we
2558            // need to see about starting one.
2559            wasVisible = win.isWinVisibleLw();
2560            if (wasVisible) {
2561
2562                int transit = WindowManagerPolicy.TRANSIT_EXIT;
2563                if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2564                    transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2565                }
2566                // Try starting an animation.
2567                if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
2568                    win.mExiting = true;
2569                }
2570                //TODO (multidisplay): Magnification is supported only for the default display.
2571                if (mAccessibilityController != null
2572                        && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
2573                    mAccessibilityController.onWindowTransitionLocked(win, transit);
2574                }
2575            }
2576            if (win.mExiting || win.mWinAnimator.isAnimating()) {
2577                // The exit animation is running... wait for it!
2578                //Slog.i(TAG, "*** Running exit animation...");
2579                win.mExiting = true;
2580                win.mRemoveOnExit = true;
2581                final DisplayContent displayContent = win.getDisplayContent();
2582                if (displayContent != null) {
2583                    displayContent.layoutNeeded = true;
2584                }
2585                final boolean focusChanged = updateFocusedWindowLocked(
2586                        UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
2587                performLayoutAndPlaceSurfacesLocked();
2588                if (win.mAppToken != null) {
2589                    win.mAppToken.updateReportedVisibilityLocked();
2590                }
2591                if (focusChanged) {
2592                    mInputMonitor.updateInputWindowsLw(false /*force*/);
2593                }
2594                //dump();
2595                Binder.restoreCallingIdentity(origId);
2596                return;
2597            }
2598        }
2599
2600        removeWindowInnerLocked(session, win);
2601        // Removing a visible window will effect the computed orientation
2602        // So just update orientation if needed.
2603        if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
2604            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2605        }
2606        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
2607        Binder.restoreCallingIdentity(origId);
2608    }
2609
2610    void removeWindowInnerLocked(Session session, WindowState win) {
2611        if (win.mRemoved) {
2612            // Nothing to do.
2613            return;
2614        }
2615
2616        for (int i=win.mChildWindows.size()-1; i>=0; i--) {
2617            WindowState cwin = win.mChildWindows.get(i);
2618            Slog.w(TAG, "Force-removing child win " + cwin + " from container "
2619                    + win);
2620            removeWindowInnerLocked(cwin.mSession, cwin);
2621        }
2622
2623        win.mRemoved = true;
2624
2625        if (mInputMethodTarget == win) {
2626            moveInputMethodWindowsIfNeededLocked(false);
2627        }
2628
2629        if (false) {
2630            RuntimeException e = new RuntimeException("here");
2631            e.fillInStackTrace();
2632            Slog.w(TAG, "Removing window " + win, e);
2633        }
2634
2635        mPolicy.removeWindowLw(win);
2636        win.removeLocked();
2637
2638        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
2639        mWindowMap.remove(win.mClient.asBinder());
2640        if (win.mAppOp != AppOpsManager.OP_NONE) {
2641            mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
2642        }
2643
2644        mPendingRemove.remove(win);
2645        mResizingWindows.remove(win);
2646        mWindowsChanged = true;
2647        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
2648
2649        if (mInputMethodWindow == win) {
2650            mInputMethodWindow = null;
2651        } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2652            mInputMethodDialogs.remove(win);
2653        }
2654
2655        final WindowToken token = win.mToken;
2656        final AppWindowToken atoken = win.mAppToken;
2657        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
2658        token.windows.remove(win);
2659        if (atoken != null) {
2660            atoken.allAppWindows.remove(win);
2661        }
2662        if (localLOGV) Slog.v(
2663                TAG, "**** Removing window " + win + ": count="
2664                + token.windows.size());
2665        if (token.windows.size() == 0) {
2666            if (!token.explicit) {
2667                WindowToken wtoken = mTokenMap.remove(token.token);
2668                Slog.w("BadTokenDebug", "removeWindowInnerLocked: Removing token=" + token + " removed=" +
2669                        wtoken + " Callers=" + Debug.getCallers(4));
2670            } else if (atoken != null) {
2671                atoken.firstWindowDrawn = false;
2672            }
2673        }
2674
2675        if (atoken != null) {
2676            if (atoken.startingWindow == win) {
2677                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
2678                atoken.startingWindow = null;
2679            } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2680                // If this is the last window and we had requested a starting
2681                // transition window, well there is no point now.
2682                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling last startingWindow");
2683                atoken.startingData = null;
2684            } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2685                // If this is the last window except for a starting transition
2686                // window, we need to get rid of the starting transition.
2687                scheduleRemoveStartingWindow(atoken);
2688            }
2689        }
2690
2691        if (win.mAttrs.type == TYPE_WALLPAPER) {
2692            mLastWallpaperTimeoutTime = 0;
2693            getDefaultDisplayContentLocked().pendingLayoutChanges |=
2694                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2695        } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2696            getDefaultDisplayContentLocked().pendingLayoutChanges |=
2697                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
2698        }
2699
2700        final WindowList windows = win.getWindowList();
2701        if (windows != null) {
2702            windows.remove(win);
2703            if (!mInLayout) {
2704                assignLayersLocked(windows);
2705                final DisplayContent displayContent = win.getDisplayContent();
2706                if (displayContent != null) {
2707                    displayContent.layoutNeeded = true;
2708                }
2709                performLayoutAndPlaceSurfacesLocked();
2710                if (win.mAppToken != null) {
2711                    win.mAppToken.updateReportedVisibilityLocked();
2712                }
2713            }
2714        }
2715
2716        mInputMonitor.updateInputWindowsLw(true /*force*/);
2717    }
2718
2719    public void updateAppOpsState() {
2720        synchronized(mWindowMap) {
2721            final int numDisplays = mDisplayContents.size();
2722            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
2723                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
2724                final int numWindows = windows.size();
2725                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
2726                    final WindowState win = windows.get(winNdx);
2727                    if (win.mAppOp != AppOpsManager.OP_NONE) {
2728                        final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
2729                                win.getOwningPackage());
2730                        win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
2731                    }
2732                }
2733            }
2734        }
2735    }
2736
2737    static void logSurface(WindowState w, String msg, RuntimeException where) {
2738        String str = "  SURFACE " + msg + ": " + w;
2739        if (where != null) {
2740            Slog.i(TAG, str, where);
2741        } else {
2742            Slog.i(TAG, str);
2743        }
2744    }
2745
2746    static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
2747        String str = "  SURFACE " + s + ": " + msg + " / " + title;
2748        if (where != null) {
2749            Slog.i(TAG, str, where);
2750        } else {
2751            Slog.i(TAG, str);
2752        }
2753    }
2754
2755    void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2756        long origId = Binder.clearCallingIdentity();
2757        try {
2758            synchronized (mWindowMap) {
2759                WindowState w = windowForClientLocked(session, client, false);
2760                if ((w != null) && w.mHasSurface) {
2761                    w.mWinAnimator.setTransparentRegionHintLocked(region);
2762                }
2763            }
2764        } finally {
2765            Binder.restoreCallingIdentity(origId);
2766        }
2767    }
2768
2769    void setInsetsWindow(Session session, IWindow client,
2770            int touchableInsets, Rect contentInsets,
2771            Rect visibleInsets, Region touchableRegion) {
2772        long origId = Binder.clearCallingIdentity();
2773        try {
2774            synchronized (mWindowMap) {
2775                WindowState w = windowForClientLocked(session, client, false);
2776                if (w != null) {
2777                    w.mGivenInsetsPending = false;
2778                    w.mGivenContentInsets.set(contentInsets);
2779                    w.mGivenVisibleInsets.set(visibleInsets);
2780                    w.mGivenTouchableRegion.set(touchableRegion);
2781                    w.mTouchableInsets = touchableInsets;
2782                    if (w.mGlobalScale != 1) {
2783                        w.mGivenContentInsets.scale(w.mGlobalScale);
2784                        w.mGivenVisibleInsets.scale(w.mGlobalScale);
2785                        w.mGivenTouchableRegion.scale(w.mGlobalScale);
2786                    }
2787                    final DisplayContent displayContent = w.getDisplayContent();
2788                    if (displayContent != null) {
2789                        displayContent.layoutNeeded = true;
2790                    }
2791                    performLayoutAndPlaceSurfacesLocked();
2792                }
2793            }
2794        } finally {
2795            Binder.restoreCallingIdentity(origId);
2796        }
2797    }
2798
2799    public void getWindowDisplayFrame(Session session, IWindow client,
2800            Rect outDisplayFrame) {
2801        synchronized(mWindowMap) {
2802            WindowState win = windowForClientLocked(session, client, false);
2803            if (win == null) {
2804                outDisplayFrame.setEmpty();
2805                return;
2806            }
2807            outDisplayFrame.set(win.mDisplayFrame);
2808        }
2809    }
2810
2811    public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2812            float xStep, float yStep) {
2813        if (window.mWallpaperX != x || window.mWallpaperY != y)  {
2814            window.mWallpaperX = x;
2815            window.mWallpaperY = y;
2816            window.mWallpaperXStep = xStep;
2817            window.mWallpaperYStep = yStep;
2818            updateWallpaperOffsetLocked(window, true);
2819        }
2820    }
2821
2822    void wallpaperCommandComplete(IBinder window, Bundle result) {
2823        synchronized (mWindowMap) {
2824            if (mWaitingOnWallpaper != null &&
2825                    mWaitingOnWallpaper.mClient.asBinder() == window) {
2826                mWaitingOnWallpaper = null;
2827                mWindowMap.notifyAll();
2828            }
2829        }
2830    }
2831
2832    public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2833            String action, int x, int y, int z, Bundle extras, boolean sync) {
2834        if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2835                || window == mUpperWallpaperTarget) {
2836            boolean doWait = sync;
2837            int curTokenIndex = mWallpaperTokens.size();
2838            while (curTokenIndex > 0) {
2839                curTokenIndex--;
2840                WindowToken token = mWallpaperTokens.get(curTokenIndex);
2841                int curWallpaperIndex = token.windows.size();
2842                while (curWallpaperIndex > 0) {
2843                    curWallpaperIndex--;
2844                    WindowState wallpaper = token.windows.get(curWallpaperIndex);
2845                    try {
2846                        wallpaper.mClient.dispatchWallpaperCommand(action,
2847                                x, y, z, extras, sync);
2848                        // We only want to be synchronous with one wallpaper.
2849                        sync = false;
2850                    } catch (RemoteException e) {
2851                    }
2852                }
2853            }
2854
2855            if (doWait) {
2856                // XXX Need to wait for result.
2857            }
2858        }
2859
2860        return null;
2861    }
2862
2863    public void setUniverseTransformLocked(WindowState window, float alpha,
2864            float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
2865        Transformation transform = window.mWinAnimator.mUniverseTransform;
2866        transform.setAlpha(alpha);
2867        Matrix matrix = transform.getMatrix();
2868        matrix.getValues(mTmpFloats);
2869        mTmpFloats[Matrix.MTRANS_X] = offx;
2870        mTmpFloats[Matrix.MTRANS_Y] = offy;
2871        mTmpFloats[Matrix.MSCALE_X] = dsdx;
2872        mTmpFloats[Matrix.MSKEW_Y] = dtdx;
2873        mTmpFloats[Matrix.MSKEW_X] = dsdy;
2874        mTmpFloats[Matrix.MSCALE_Y] = dtdy;
2875        matrix.setValues(mTmpFloats);
2876        final DisplayContent displayContent = window.getDisplayContent();
2877        if (displayContent == null) {
2878            return;
2879        }
2880
2881        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2882        final RectF dispRect = new RectF(0, 0,
2883                displayInfo.logicalWidth, displayInfo.logicalHeight);
2884        matrix.mapRect(dispRect);
2885        window.mGivenTouchableRegion.set(0, 0,
2886                displayInfo.logicalWidth, displayInfo.logicalHeight);
2887        window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
2888                (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
2889        window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
2890        displayContent.layoutNeeded = true;
2891        performLayoutAndPlaceSurfacesLocked();
2892    }
2893
2894    public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
2895        synchronized (mWindowMap) {
2896            if (mAccessibilityController != null) {
2897                WindowState window = mWindowMap.get(token);
2898                //TODO (multidisplay): Magnification is supported only for the default display.
2899                if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
2900                    mAccessibilityController.onRectangleOnScreenRequestedLocked(rectangle);
2901                }
2902            }
2903        }
2904    }
2905
2906    public IWindowId getWindowId(IBinder token) {
2907        synchronized (mWindowMap) {
2908            WindowState window = mWindowMap.get(token);
2909            return window != null ? window.mWindowId : null;
2910        }
2911    }
2912
2913    public int relayoutWindow(Session session, IWindow client, int seq,
2914            WindowManager.LayoutParams attrs, int requestedWidth,
2915            int requestedHeight, int viewVisibility, int flags,
2916            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
2917            Rect outVisibleInsets, Rect outStableInsets, Configuration outConfig,
2918            Surface outSurface) {
2919        boolean toBeDisplayed = false;
2920        boolean inTouchMode;
2921        boolean configChanged;
2922        boolean surfaceChanged = false;
2923        boolean animating;
2924        boolean hasStatusBarPermission =
2925                mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
2926                        == PackageManager.PERMISSION_GRANTED;
2927
2928        long origId = Binder.clearCallingIdentity();
2929
2930        synchronized(mWindowMap) {
2931            WindowState win = windowForClientLocked(session, client, false);
2932            if (win == null) {
2933                return 0;
2934            }
2935            WindowStateAnimator winAnimator = win.mWinAnimator;
2936            if (win.mRequestedWidth != requestedWidth
2937                    || win.mRequestedHeight != requestedHeight) {
2938                win.mLayoutNeeded = true;
2939                win.mRequestedWidth = requestedWidth;
2940                win.mRequestedHeight = requestedHeight;
2941            }
2942
2943            if (attrs != null) {
2944                mPolicy.adjustWindowParamsLw(attrs);
2945            }
2946
2947            // if they don't have the permission, mask out the status bar bits
2948            int systemUiVisibility = 0;
2949            if (attrs != null) {
2950                systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
2951                if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
2952                    if (!hasStatusBarPermission) {
2953                        systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
2954                    }
2955                }
2956            }
2957
2958            if (attrs != null && seq == win.mSeq) {
2959                win.mSystemUiVisibility = systemUiVisibility;
2960            }
2961
2962            winAnimator.mSurfaceDestroyDeferred =
2963                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
2964
2965            int attrChanges = 0;
2966            int flagChanges = 0;
2967            if (attrs != null) {
2968                if (win.mAttrs.type != attrs.type) {
2969                    throw new IllegalArgumentException(
2970                            "Window type can not be changed after the window is added.");
2971                }
2972                flagChanges = win.mAttrs.flags ^= attrs.flags;
2973                attrChanges = win.mAttrs.copyFrom(attrs);
2974                if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
2975                        | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
2976                    win.mLayoutNeeded = true;
2977                }
2978            }
2979
2980            if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
2981                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
2982
2983            win.mEnforceSizeCompat =
2984                    (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
2985
2986            if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2987                winAnimator.mAlpha = attrs.alpha;
2988            }
2989
2990            final boolean scaledWindow =
2991                ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2992
2993            if (scaledWindow) {
2994                // requested{Width|Height} Surface's physical size
2995                // attrs.{width|height} Size on screen
2996                win.mHScale = (attrs.width  != requestedWidth)  ?
2997                        (attrs.width  / (float)requestedWidth) : 1.0f;
2998                win.mVScale = (attrs.height != requestedHeight) ?
2999                        (attrs.height / (float)requestedHeight) : 1.0f;
3000            } else {
3001                win.mHScale = win.mVScale = 1;
3002            }
3003
3004            boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
3005
3006            final boolean isDefaultDisplay = win.isDefaultDisplay();
3007            boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
3008                    || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
3009                    || (!win.mRelayoutCalled));
3010
3011            boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
3012                    && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
3013            wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
3014
3015            win.mRelayoutCalled = true;
3016            final int oldVisibility = win.mViewVisibility;
3017            win.mViewVisibility = viewVisibility;
3018            if (DEBUG_SCREEN_ON) {
3019                RuntimeException stack = new RuntimeException();
3020                stack.fillInStackTrace();
3021                Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility
3022                        + " newVis=" + viewVisibility, stack);
3023            }
3024            if (viewVisibility == View.VISIBLE &&
3025                    (win.mAppToken == null || !win.mAppToken.clientHidden)) {
3026                toBeDisplayed = !win.isVisibleLw();
3027                if (win.mExiting) {
3028                    winAnimator.cancelExitAnimationForNextAnimationLocked();
3029                    win.mExiting = false;
3030                }
3031                if (win.mDestroying) {
3032                    win.mDestroying = false;
3033                    mDestroySurface.remove(win);
3034                }
3035                if (oldVisibility == View.GONE) {
3036                    winAnimator.mEnterAnimationPending = true;
3037                }
3038                if (toBeDisplayed) {
3039                    if (win.isDrawnLw() && okToDisplay()) {
3040                        winAnimator.applyEnterAnimationLocked();
3041                    }
3042                    if ((win.mAttrs.flags
3043                            & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
3044                        if (DEBUG_VISIBILITY) Slog.v(TAG,
3045                                "Relayout window turning screen on: " + win);
3046                        win.mTurnOnScreen = true;
3047                    }
3048                    if (win.isConfigChanged()) {
3049                        if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
3050                                + " visible with new config: " + mCurConfiguration);
3051                        outConfig.setTo(mCurConfiguration);
3052                    }
3053                }
3054                if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
3055                    // To change the format, we need to re-build the surface.
3056                    winAnimator.destroySurfaceLocked();
3057                    toBeDisplayed = true;
3058                    surfaceChanged = true;
3059                }
3060                try {
3061                    if (!win.mHasSurface) {
3062                        surfaceChanged = true;
3063                    }
3064                    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
3065                    if (surfaceControl != null) {
3066                        outSurface.copyFrom(surfaceControl);
3067                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
3068                                "  OUT SURFACE " + outSurface + ": copied");
3069                    } else {
3070                        // For some reason there isn't a surface.  Clear the
3071                        // caller's object so they see the same state.
3072                        outSurface.release();
3073                    }
3074                } catch (Exception e) {
3075                    mInputMonitor.updateInputWindowsLw(true /*force*/);
3076
3077                    Slog.w(TAG, "Exception thrown when creating surface for client "
3078                             + client + " (" + win.mAttrs.getTitle() + ")",
3079                             e);
3080                    Binder.restoreCallingIdentity(origId);
3081                    return 0;
3082                }
3083                if (toBeDisplayed) {
3084                    focusMayChange = isDefaultDisplay;
3085                }
3086                if (win.mAttrs.type == TYPE_INPUT_METHOD
3087                        && mInputMethodWindow == null) {
3088                    mInputMethodWindow = win;
3089                    imMayMove = true;
3090                }
3091                if (win.mAttrs.type == TYPE_BASE_APPLICATION
3092                        && win.mAppToken != null
3093                        && win.mAppToken.startingWindow != null) {
3094                    // Special handling of starting window over the base
3095                    // window of the app: propagate lock screen flags to it,
3096                    // to provide the correct semantics while starting.
3097                    final int mask =
3098                        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
3099                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
3100                        | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
3101                    WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
3102                    sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
3103                }
3104            } else {
3105                winAnimator.mEnterAnimationPending = false;
3106                if (winAnimator.mSurfaceControl != null) {
3107                    if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
3108                            + ": mExiting=" + win.mExiting);
3109                    // If we are not currently running the exit animation, we
3110                    // need to see about starting one.
3111                    if (!win.mExiting) {
3112                        surfaceChanged = true;
3113                        // Try starting an animation; if there isn't one, we
3114                        // can destroy the surface right away.
3115                        int transit = WindowManagerPolicy.TRANSIT_EXIT;
3116                        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
3117                            transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
3118                        }
3119                        if (win.isWinVisibleLw() &&
3120                                winAnimator.applyAnimationLocked(transit, false)) {
3121                            focusMayChange = isDefaultDisplay;
3122                            win.mExiting = true;
3123                        } else if (win.mWinAnimator.isAnimating()) {
3124                            // Currently in a hide animation... turn this into
3125                            // an exit.
3126                            win.mExiting = true;
3127                        } else if (win == mWallpaperTarget) {
3128                            // If the wallpaper is currently behind this
3129                            // window, we need to change both of them inside
3130                            // of a transaction to avoid artifacts.
3131                            win.mExiting = true;
3132                            win.mWinAnimator.mAnimating = true;
3133                        } else {
3134                            if (mInputMethodWindow == win) {
3135                                mInputMethodWindow = null;
3136                            }
3137                            winAnimator.destroySurfaceLocked();
3138                        }
3139                        //TODO (multidisplay): Magnification is supported only for the default
3140                        if (mAccessibilityController != null
3141                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
3142                            mAccessibilityController.onWindowTransitionLocked(win, transit);
3143                        }
3144                    }
3145                }
3146
3147                outSurface.release();
3148                if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
3149            }
3150
3151            if (focusMayChange) {
3152                //System.out.println("Focus may change: " + win.mAttrs.getTitle());
3153                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
3154                        false /*updateInputWindows*/)) {
3155                    imMayMove = false;
3156                }
3157                //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
3158            }
3159
3160            // updateFocusedWindowLocked() already assigned layers so we only need to
3161            // reassign them at this point if the IM window state gets shuffled
3162            if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
3163                // Little hack here -- we -should- be able to rely on the
3164                // function to return true if the IME has moved and needs
3165                // its layer recomputed.  However, if the IME was hidden
3166                // and isn't actually moved in the list, its layer may be
3167                // out of data so we make sure to recompute it.
3168                assignLayersLocked(win.getWindowList());
3169            }
3170
3171            if (wallpaperMayMove) {
3172                getDefaultDisplayContentLocked().pendingLayoutChanges |=
3173                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3174            }
3175
3176            final DisplayContent displayContent = win.getDisplayContent();
3177            if (displayContent != null) {
3178                displayContent.layoutNeeded = true;
3179            }
3180            win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
3181            configChanged = updateOrientationFromAppTokensLocked(false);
3182            performLayoutAndPlaceSurfacesLocked();
3183            if (toBeDisplayed && win.mIsWallpaper) {
3184                DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3185                updateWallpaperOffsetLocked(win,
3186                        displayInfo.logicalWidth, displayInfo.logicalHeight, false);
3187            }
3188            if (win.mAppToken != null) {
3189                win.mAppToken.updateReportedVisibilityLocked();
3190            }
3191            outFrame.set(win.mCompatFrame);
3192            outOverscanInsets.set(win.mOverscanInsets);
3193            outContentInsets.set(win.mContentInsets);
3194            outVisibleInsets.set(win.mVisibleInsets);
3195            outStableInsets.set(win.mStableInsets);
3196            if (localLOGV) Slog.v(
3197                TAG, "Relayout given client " + client.asBinder()
3198                + ", requestedWidth=" + requestedWidth
3199                + ", requestedHeight=" + requestedHeight
3200                + ", viewVisibility=" + viewVisibility
3201                + "\nRelayout returning frame=" + outFrame
3202                + ", surface=" + outSurface);
3203
3204            if (localLOGV || DEBUG_FOCUS) Slog.v(
3205                TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
3206
3207            inTouchMode = mInTouchMode;
3208            animating = mAnimator.mAnimating && win.mWinAnimator.isAnimating();
3209            if (animating && !mRelayoutWhileAnimating.contains(win)) {
3210                mRelayoutWhileAnimating.add(win);
3211            }
3212
3213            mInputMonitor.updateInputWindowsLw(true /*force*/);
3214
3215            if (DEBUG_LAYOUT) {
3216                Slog.v(TAG, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
3217            }
3218        }
3219
3220        if (configChanged) {
3221            sendNewConfiguration();
3222        }
3223
3224        Binder.restoreCallingIdentity(origId);
3225
3226        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
3227                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
3228                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
3229                | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0);
3230    }
3231
3232    public void performDeferredDestroyWindow(Session session, IWindow client) {
3233        long origId = Binder.clearCallingIdentity();
3234
3235        try {
3236            synchronized (mWindowMap) {
3237                WindowState win = windowForClientLocked(session, client, false);
3238                if (win == null) {
3239                    return;
3240                }
3241                win.mWinAnimator.destroyDeferredSurfaceLocked();
3242            }
3243        } finally {
3244            Binder.restoreCallingIdentity(origId);
3245        }
3246    }
3247
3248    public boolean outOfMemoryWindow(Session session, IWindow client) {
3249        long origId = Binder.clearCallingIdentity();
3250
3251        try {
3252            synchronized (mWindowMap) {
3253                WindowState win = windowForClientLocked(session, client, false);
3254                if (win == null) {
3255                    return false;
3256                }
3257                return reclaimSomeSurfaceMemoryLocked(win.mWinAnimator, "from-client", false);
3258            }
3259        } finally {
3260            Binder.restoreCallingIdentity(origId);
3261        }
3262    }
3263
3264    public void finishDrawingWindow(Session session, IWindow client) {
3265        final long origId = Binder.clearCallingIdentity();
3266        try {
3267            synchronized (mWindowMap) {
3268                WindowState win = windowForClientLocked(session, client, false);
3269                if (win != null && win.mWinAnimator.finishDrawingLocked()) {
3270                    if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
3271                        getDefaultDisplayContentLocked().pendingLayoutChanges |=
3272                                WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
3273                    }
3274                    final DisplayContent displayContent = win.getDisplayContent();
3275                    if (displayContent != null) {
3276                        displayContent.layoutNeeded = true;
3277                    }
3278                    requestTraversalLocked();
3279                }
3280            }
3281        } finally {
3282            Binder.restoreCallingIdentity(origId);
3283        }
3284    }
3285
3286    private boolean applyAnimationLocked(AppWindowToken atoken,
3287            WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) {
3288        // Only apply an animation if the display isn't frozen.  If it is
3289        // frozen, there is no reason to animate and it can cause strange
3290        // artifacts when we unfreeze the display if some different animation
3291        // is running.
3292        if (okToDisplay()) {
3293            DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
3294            final int width = displayInfo.appWidth;
3295            final int height = displayInfo.appHeight;
3296            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "applyAnimation: atoken="
3297                    + atoken);
3298
3299            // Determine the visible rect to calculate the thumbnail clip
3300            WindowState win = atoken.findMainWindow();
3301            Rect containingFrame = new Rect(0, 0, width, height);
3302            Rect contentInsets = new Rect();
3303            boolean isFullScreen = true;
3304            if (win != null) {
3305                if (win.mContainingFrame != null) {
3306                    containingFrame.set(win.mContainingFrame);
3307                }
3308                if (win.mContentInsets != null) {
3309                    contentInsets.set(win.mContentInsets);
3310                }
3311                isFullScreen =
3312                        ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) ==
3313                                SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
3314            }
3315
3316            if (atoken.mLaunchTaskBehind) {
3317                // Differentiate the two animations. This one which is briefly on the screen
3318                // gets the !enter animation, and the other activity which remains on the
3319                // screen gets the enter animation. Both appear in the mOpeningApps set.
3320                enter = false;
3321            }
3322            Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
3323                    mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen,
3324                    isVoiceInteraction);
3325            if (a != null) {
3326                if (DEBUG_ANIM) {
3327                    RuntimeException e = null;
3328                    if (!HIDE_STACK_CRAWLS) {
3329                        e = new RuntimeException();
3330                        e.fillInStackTrace();
3331                    }
3332                    Slog.v(TAG, "Loaded animation " + a + " for " + atoken, e);
3333                }
3334                atoken.mAppAnimator.setAnimation(a, width, height);
3335            }
3336        } else {
3337            atoken.mAppAnimator.clearAnimation();
3338        }
3339
3340        return atoken.mAppAnimator.animation != null;
3341    }
3342
3343    // -------------------------------------------------------------
3344    // Application Window Tokens
3345    // -------------------------------------------------------------
3346
3347    public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
3348        synchronized (mWindowMap) {
3349            int t = tasks.size() - 1;
3350            if (t < 0) {
3351                Slog.w(TAG, "validateAppTokens: empty task list");
3352                return;
3353            }
3354
3355            TaskGroup task = tasks.get(0);
3356            int taskId = task.taskId;
3357            Task targetTask = mTaskIdToTask.get(taskId);
3358            DisplayContent displayContent = targetTask.getDisplayContent();
3359            if (displayContent == null) {
3360                Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
3361                return;
3362            }
3363
3364            final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
3365            int taskNdx;
3366            for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
3367                AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
3368                task = tasks.get(t);
3369                List<IApplicationToken> tokens = task.tokens;
3370
3371                DisplayContent lastDisplayContent = displayContent;
3372                displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
3373                if (displayContent != lastDisplayContent) {
3374                    Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
3375                    return;
3376                }
3377
3378                int tokenNdx;
3379                int v;
3380                for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
3381                        tokenNdx >= 0 && v >= 0; ) {
3382                    final AppWindowToken atoken = localTokens.get(tokenNdx);
3383                    if (atoken.removed) {
3384                        --tokenNdx;
3385                        continue;
3386                    }
3387                    if (tokens.get(v) != atoken.token) {
3388                        break;
3389                    }
3390                    --tokenNdx;
3391                    v--;
3392                }
3393
3394                if (tokenNdx >= 0 || v >= 0) {
3395                    break;
3396                }
3397            }
3398
3399            if (taskNdx >= 0 || t >= 0) {
3400                Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
3401                Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
3402                Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
3403            }
3404        }
3405    }
3406
3407    public void validateStackOrder(Integer[] remoteStackIds) {
3408        // TODO:
3409    }
3410
3411    boolean checkCallingPermission(String permission, String func) {
3412        // Quick check: if the calling permission is me, it's all okay.
3413        if (Binder.getCallingPid() == Process.myPid()) {
3414            return true;
3415        }
3416
3417        if (mContext.checkCallingPermission(permission)
3418                == PackageManager.PERMISSION_GRANTED) {
3419            return true;
3420        }
3421        String msg = "Permission Denial: " + func + " from pid="
3422                + Binder.getCallingPid()
3423                + ", uid=" + Binder.getCallingUid()
3424                + " requires " + permission;
3425        Slog.w(TAG, msg);
3426        return false;
3427    }
3428
3429    boolean okToDisplay() {
3430        return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully();
3431    }
3432
3433    AppWindowToken findAppWindowToken(IBinder token) {
3434        WindowToken wtoken = mTokenMap.get(token);
3435        if (wtoken == null) {
3436            return null;
3437        }
3438        return wtoken.appWindowToken;
3439    }
3440
3441    @Override
3442    public void addWindowToken(IBinder token, int type) {
3443        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3444                "addWindowToken()")) {
3445            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3446        }
3447
3448        synchronized(mWindowMap) {
3449            WindowToken wtoken = mTokenMap.get(token);
3450            if (wtoken != null) {
3451                Slog.w(TAG, "Attempted to add existing input method token: " + token);
3452                return;
3453            }
3454            wtoken = new WindowToken(this, token, type, true);
3455            Slog.w("BadTokenDebug", "addWindowToken: Adding token=" + token + " wtoken=" + wtoken);
3456            mTokenMap.put(token, wtoken);
3457            if (type == TYPE_WALLPAPER) {
3458                mWallpaperTokens.add(wtoken);
3459            }
3460        }
3461    }
3462
3463    @Override
3464    public void removeWindowToken(IBinder token) {
3465        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3466                "removeWindowToken()")) {
3467            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3468        }
3469
3470        final long origId = Binder.clearCallingIdentity();
3471        synchronized(mWindowMap) {
3472            DisplayContent displayContent = null;
3473            WindowToken wtoken = mTokenMap.remove(token);
3474            Slog.w("BadTokenDebug", "removeWindowToken: Removing token=" + token + " removed=" + wtoken
3475                    + " Callers=" + Debug.getCallers(3));
3476            if (wtoken != null) {
3477                boolean delayed = false;
3478                if (!wtoken.hidden) {
3479                    final int N = wtoken.windows.size();
3480                    boolean changed = false;
3481
3482                    for (int i=0; i<N; i++) {
3483                        WindowState win = wtoken.windows.get(i);
3484                        displayContent = win.getDisplayContent();
3485
3486                        if (win.mWinAnimator.isAnimating()) {
3487                            delayed = true;
3488                        }
3489
3490                        if (win.isVisibleNow()) {
3491                            win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
3492                                    false);
3493                            //TODO (multidisplay): Magnification is supported only for the default
3494                            if (mAccessibilityController != null && win.isDefaultDisplay()) {
3495                                mAccessibilityController.onWindowTransitionLocked(win,
3496                                        WindowManagerPolicy.TRANSIT_EXIT);
3497                            }
3498                            changed = true;
3499                            if (displayContent != null) {
3500                                displayContent.layoutNeeded = true;
3501                            }
3502                        }
3503                    }
3504
3505                    wtoken.hidden = true;
3506
3507                    if (changed) {
3508                        performLayoutAndPlaceSurfacesLocked();
3509                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
3510                                false /*updateInputWindows*/);
3511                    }
3512
3513                    if (delayed) {
3514                        if (displayContent != null) {
3515                            displayContent.mExitingTokens.add(wtoken);
3516                        }
3517                    } else if (wtoken.windowType == TYPE_WALLPAPER) {
3518                        mWallpaperTokens.remove(wtoken);
3519                    }
3520                }
3521
3522                mInputMonitor.updateInputWindowsLw(true /*force*/);
3523            } else {
3524                Slog.w(TAG, "Attempted to remove non-existing token: " + token);
3525            }
3526        }
3527        Binder.restoreCallingIdentity(origId);
3528    }
3529
3530    private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
3531        if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
3532                + " atoken=" + atoken);
3533        final TaskStack stack = mStackIdToStack.get(stackId);
3534        if (stack == null) {
3535            throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
3536        }
3537        EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
3538        Task task = new Task(atoken, stack, userId);
3539        mTaskIdToTask.put(taskId, task);
3540        stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
3541        return task;
3542    }
3543
3544    @Override
3545    public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
3546            int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
3547            int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
3548        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3549                "addAppToken()")) {
3550            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3551        }
3552
3553        // Get the dispatching timeout here while we are not holding any locks so that it
3554        // can be cached by the AppWindowToken.  The timeout value is used later by the
3555        // input dispatcher in code that does hold locks.  If we did not cache the value
3556        // here we would run the chance of introducing a deadlock between the window manager
3557        // (which holds locks while updating the input dispatcher state) and the activity manager
3558        // (which holds locks while querying the application token).
3559        long inputDispatchingTimeoutNanos;
3560        try {
3561            inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3562        } catch (RemoteException ex) {
3563            Slog.w(TAG, "Could not get dispatching timeout.", ex);
3564            inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3565        }
3566
3567        synchronized(mWindowMap) {
3568            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3569            if (atoken != null) {
3570                Slog.w(TAG, "Attempted to add existing app token: " + token);
3571                return;
3572            }
3573            atoken = new AppWindowToken(this, token, voiceInteraction);
3574            atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
3575            atoken.groupId = taskId;
3576            atoken.appFullscreen = fullscreen;
3577            atoken.showWhenLocked = showWhenLocked;
3578            atoken.requestedOrientation = requestedOrientation;
3579            atoken.layoutConfigChanges = (configChanges &
3580                    (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
3581            atoken.mLaunchTaskBehind = launchTaskBehind;
3582            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
3583                    + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
3584
3585            Task task = mTaskIdToTask.get(taskId);
3586            if (task == null) {
3587                createTask(taskId, stackId, userId, atoken);
3588            } else {
3589                task.addAppToken(addPos, atoken);
3590            }
3591
3592            Slog.w("BadTokenDebug", "addAppToken: Adding token=" + token.asBinder() + " atoken=" + atoken);
3593            mTokenMap.put(token.asBinder(), atoken);
3594
3595            // Application tokens start out hidden.
3596            atoken.hidden = true;
3597            atoken.hiddenRequested = true;
3598
3599            //dump();
3600        }
3601    }
3602
3603    @Override
3604    public void setAppGroupId(IBinder token, int groupId) {
3605        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3606                "setAppGroupId()")) {
3607            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3608        }
3609
3610        synchronized(mWindowMap) {
3611            final AppWindowToken atoken = findAppWindowToken(token);
3612            if (atoken == null) {
3613                Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
3614                return;
3615            }
3616            final Task oldTask = mTaskIdToTask.get(atoken.groupId);
3617            oldTask.removeAppToken(atoken);
3618
3619            atoken.groupId = groupId;
3620            Task newTask = mTaskIdToTask.get(groupId);
3621            if (newTask == null) {
3622                newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
3623            } else {
3624                newTask.mAppTokens.add(atoken);
3625            }
3626        }
3627    }
3628
3629    public int getOrientationFromWindowsLocked() {
3630        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
3631            // If the display is frozen, some activities may be in the middle
3632            // of restarting, and thus have removed their old window.  If the
3633            // window has the flag to hide the lock screen, then the lock screen
3634            // can re-appear and inflict its own orientation on us.  Keep the
3635            // orientation stable until this all settles down.
3636            return mLastWindowForcedOrientation;
3637        }
3638
3639        // TODO(multidisplay): Change to the correct display.
3640        final WindowList windows = getDefaultWindowListLocked();
3641        int pos = windows.size() - 1;
3642        while (pos >= 0) {
3643            WindowState win = windows.get(pos);
3644            pos--;
3645            if (win.mAppToken != null) {
3646                // We hit an application window. so the orientation will be determined by the
3647                // app window. No point in continuing further.
3648                return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3649            }
3650            if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
3651                continue;
3652            }
3653            int req = win.mAttrs.screenOrientation;
3654            if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3655                    (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3656                continue;
3657            }
3658
3659            if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
3660            return (mLastWindowForcedOrientation=req);
3661        }
3662        return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3663    }
3664
3665    public int getOrientationFromAppTokensLocked() {
3666        int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3667        boolean findingBehind = false;
3668        boolean lastFullscreen = false;
3669        // TODO: Multi window.
3670        DisplayContent displayContent = getDefaultDisplayContentLocked();
3671        final ArrayList<Task> tasks = displayContent.getTasks();
3672        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
3673            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
3674            final int firstToken = tokens.size() - 1;
3675            for (int tokenNdx = firstToken; tokenNdx >= 0; --tokenNdx) {
3676                final AppWindowToken atoken = tokens.get(tokenNdx);
3677
3678                if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
3679
3680                // if we're about to tear down this window and not seek for
3681                // the behind activity, don't use it for orientation
3682                if (!findingBehind
3683                        && (!atoken.hidden && atoken.hiddenRequested)) {
3684                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3685                            + " -- going to hide");
3686                    continue;
3687                }
3688
3689                if (tokenNdx == firstToken) {
3690                    // If we have hit a new Task, and the bottom
3691                    // of the previous group didn't explicitly say to use
3692                    // the orientation behind it, and the last app was
3693                    // full screen, then we'll stick with the
3694                    // user's orientation.
3695                    if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3696                            && lastFullscreen) {
3697                        if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3698                                + " -- end of group, return " + lastOrientation);
3699                        return lastOrientation;
3700                    }
3701                }
3702
3703                // We ignore any hidden applications on the top.
3704                if (atoken.hiddenRequested || atoken.willBeHidden) {
3705                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping " + atoken
3706                            + " -- hidden on top");
3707                    continue;
3708                }
3709
3710                if (tokenNdx == 0) {
3711                    // Last token in this task.
3712                    lastOrientation = atoken.requestedOrientation;
3713                }
3714
3715                int or = atoken.requestedOrientation;
3716                // If this application is fullscreen, and didn't explicitly say
3717                // to use the orientation behind it, then just take whatever
3718                // orientation it has and ignores whatever is under it.
3719                lastFullscreen = atoken.appFullscreen;
3720                if (lastFullscreen
3721                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3722                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3723                            + " -- full screen, return " + or);
3724                    return or;
3725                }
3726                // If this application has requested an explicit orientation,
3727                // then use it.
3728                if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
3729                        && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3730                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
3731                            + " -- explicitly set, return " + or);
3732                    return or;
3733                }
3734                findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3735            }
3736        }
3737        if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
3738        return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3739    }
3740
3741    @Override
3742    public Configuration updateOrientationFromAppTokens(
3743            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3744        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3745                "updateOrientationFromAppTokens()")) {
3746            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3747        }
3748
3749        Configuration config = null;
3750        long ident = Binder.clearCallingIdentity();
3751
3752        synchronized(mWindowMap) {
3753            config = updateOrientationFromAppTokensLocked(currentConfig,
3754                    freezeThisOneIfNeeded);
3755        }
3756
3757        Binder.restoreCallingIdentity(ident);
3758        return config;
3759    }
3760
3761    private Configuration updateOrientationFromAppTokensLocked(
3762            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3763        Configuration config = null;
3764
3765        if (updateOrientationFromAppTokensLocked(false)) {
3766            if (freezeThisOneIfNeeded != null) {
3767                AppWindowToken atoken = findAppWindowToken(freezeThisOneIfNeeded);
3768                if (atoken != null) {
3769                    startAppFreezingScreenLocked(atoken);
3770                }
3771            }
3772            config = computeNewConfigurationLocked();
3773
3774        } else if (currentConfig != null) {
3775            // No obvious action we need to take, but if our current
3776            // state mismatches the activity manager's, update it,
3777            // disregarding font scale, which should remain set to
3778            // the value of the previous configuration.
3779            mTempConfiguration.setToDefaults();
3780            mTempConfiguration.fontScale = currentConfig.fontScale;
3781            if (computeScreenConfigurationLocked(mTempConfiguration)) {
3782                if (currentConfig.diff(mTempConfiguration) != 0) {
3783                    mWaitingForConfig = true;
3784                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
3785                    displayContent.layoutNeeded = true;
3786                    int anim[] = new int[2];
3787                    if (displayContent.isDimming()) {
3788                        anim[0] = anim[1] = 0;
3789                    } else {
3790                        mPolicy.selectRotationAnimationLw(anim);
3791                    }
3792                    startFreezingDisplayLocked(false, anim[0], anim[1]);
3793                    config = new Configuration(mTempConfiguration);
3794                }
3795            }
3796        }
3797
3798        return config;
3799    }
3800
3801    /*
3802     * Determine the new desired orientation of the display, returning
3803     * a non-null new Configuration if it has changed from the current
3804     * orientation.  IF TRUE IS RETURNED SOMEONE MUST CALL
3805     * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3806     * SCREEN.  This will typically be done for you if you call
3807     * sendNewConfiguration().
3808     *
3809     * The orientation is computed from non-application windows first. If none of
3810     * the non-application windows specify orientation, the orientation is computed from
3811     * application tokens.
3812     * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3813     * android.os.IBinder)
3814     */
3815    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
3816        long ident = Binder.clearCallingIdentity();
3817        try {
3818            int req = getOrientationFromWindowsLocked();
3819            if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3820                req = getOrientationFromAppTokensLocked();
3821            }
3822
3823            if (req != mForcedAppOrientation) {
3824                mForcedAppOrientation = req;
3825                //send a message to Policy indicating orientation change to take
3826                //action like disabling/enabling sensors etc.,
3827                mPolicy.setCurrentOrientationLw(req);
3828                if (updateRotationUncheckedLocked(inTransaction)) {
3829                    // changed
3830                    return true;
3831                }
3832            }
3833
3834            return false;
3835        } finally {
3836            Binder.restoreCallingIdentity(ident);
3837        }
3838    }
3839
3840    @Override
3841    public void setNewConfiguration(Configuration config) {
3842        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3843                "setNewConfiguration()")) {
3844            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3845        }
3846
3847        synchronized(mWindowMap) {
3848            mCurConfiguration = new Configuration(config);
3849            if (mWaitingForConfig) {
3850                mWaitingForConfig = false;
3851                mLastFinishedFreezeSource = "new-config";
3852            }
3853            performLayoutAndPlaceSurfacesLocked();
3854        }
3855    }
3856
3857    @Override
3858    public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3859        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3860                "setAppOrientation()")) {
3861            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3862        }
3863
3864        synchronized(mWindowMap) {
3865            AppWindowToken atoken = findAppWindowToken(token.asBinder());
3866            if (atoken == null) {
3867                Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3868                return;
3869            }
3870
3871            atoken.requestedOrientation = requestedOrientation;
3872        }
3873    }
3874
3875    @Override
3876    public int getAppOrientation(IApplicationToken token) {
3877        synchronized(mWindowMap) {
3878            AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3879            if (wtoken == null) {
3880                return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3881            }
3882
3883            return wtoken.requestedOrientation;
3884        }
3885    }
3886
3887    /** Call while in a Surface transaction. */
3888    void setFocusedStackLayer() {
3889        mFocusedStackLayer = 0;
3890        if (mFocusedApp != null) {
3891            final WindowList windows = mFocusedApp.allAppWindows;
3892            for (int i = windows.size() - 1; i >= 0; --i) {
3893                final WindowState win = windows.get(i);
3894                final int animLayer = win.mWinAnimator.mAnimLayer;
3895                if (win.mAttachedWindow == null && win.isVisibleLw() &&
3896                        animLayer > mFocusedStackLayer) {
3897                    mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK;
3898                }
3899            }
3900        }
3901        if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" +
3902                mFocusedStackLayer);
3903        mFocusedStackFrame.setLayer(mFocusedStackLayer);
3904    }
3905
3906    void setFocusedStackFrame() {
3907        final TaskStack stack;
3908        if (mFocusedApp != null) {
3909            Task task = mTaskIdToTask.get(mFocusedApp.groupId);
3910            stack = task.mStack;
3911            final DisplayContent displayContent = task.getDisplayContent();
3912            if (displayContent != null) {
3913                displayContent.setTouchExcludeRegion(stack);
3914            }
3915        } else {
3916            stack = null;
3917        }
3918        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
3919        SurfaceControl.openTransaction();
3920        try {
3921            if (stack == null) {
3922                mFocusedStackFrame.setVisibility(false);
3923            } else {
3924                mFocusedStackFrame.setBounds(stack);
3925                final boolean multipleStacks = !stack.isFullscreen();
3926                mFocusedStackFrame.setVisibility(multipleStacks);
3927            }
3928        } finally {
3929            SurfaceControl.closeTransaction();
3930            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
3931        }
3932    }
3933
3934    @Override
3935    public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3936        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3937                "setFocusedApp()")) {
3938            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3939        }
3940
3941        synchronized(mWindowMap) {
3942            final AppWindowToken newFocus;
3943            if (token == null) {
3944                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
3945                newFocus = null;
3946            } else {
3947                newFocus = findAppWindowToken(token);
3948                if (newFocus == null) {
3949                    Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3950                }
3951                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
3952                        + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
3953            }
3954
3955            final boolean changed = mFocusedApp != newFocus;
3956            if (changed) {
3957                mFocusedApp = newFocus;
3958                mInputMonitor.setFocusedAppLw(newFocus);
3959            }
3960
3961            if (moveFocusNow && changed) {
3962                final long origId = Binder.clearCallingIdentity();
3963                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3964                Binder.restoreCallingIdentity(origId);
3965            }
3966        }
3967    }
3968
3969    @Override
3970    public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
3971        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3972                "prepareAppTransition()")) {
3973            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3974        }
3975
3976        synchronized(mWindowMap) {
3977            if (DEBUG_APP_TRANSITIONS) Slog.v(
3978                    TAG, "Prepare app transition: transit=" + transit
3979                    + " " + mAppTransition
3980                    + " alwaysKeepCurrent=" + alwaysKeepCurrent
3981                    + " Callers=" + Debug.getCallers(3));
3982            if (!mAppTransition.isTransitionSet() || mAppTransition.isTransitionNone()) {
3983                mAppTransition.setAppTransition(transit);
3984            } else if (!alwaysKeepCurrent) {
3985                if (transit == AppTransition.TRANSIT_TASK_OPEN
3986                        && mAppTransition.isTransitionEqual(
3987                                AppTransition.TRANSIT_TASK_CLOSE)) {
3988                    // Opening a new task always supersedes a close for the anim.
3989                    mAppTransition.setAppTransition(transit);
3990                } else if (transit == AppTransition.TRANSIT_ACTIVITY_OPEN
3991                        && mAppTransition.isTransitionEqual(
3992                            AppTransition.TRANSIT_ACTIVITY_CLOSE)) {
3993                    // Opening a new activity always supersedes a close for the anim.
3994                    mAppTransition.setAppTransition(transit);
3995                }
3996            }
3997            if (okToDisplay()) {
3998                mAppTransition.prepare();
3999                mStartingIconInTransition = false;
4000                mSkipAppTransitionAnimation = false;
4001                mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
4002                mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
4003            }
4004        }
4005    }
4006
4007    @Override
4008    public int getPendingAppTransition() {
4009        return mAppTransition.getAppTransition();
4010    }
4011
4012    @Override
4013    public void overridePendingAppTransition(String packageName,
4014            int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
4015        synchronized(mWindowMap) {
4016            mAppTransition.overridePendingAppTransition(packageName, enterAnim, exitAnim,
4017                    startedCallback);
4018        }
4019    }
4020
4021    @Override
4022    public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
4023            int startHeight) {
4024        synchronized(mWindowMap) {
4025            mAppTransition.overridePendingAppTransitionScaleUp(startX, startY, startWidth,
4026                    startHeight);
4027        }
4028    }
4029
4030    @Override
4031    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
4032            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
4033        synchronized(mWindowMap) {
4034            mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
4035                    startedCallback, scaleUp);
4036        }
4037    }
4038
4039    @Override
4040    public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
4041            int startY, IRemoteCallback startedCallback, boolean scaleUp) {
4042        synchronized(mWindowMap) {
4043            mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
4044                    startY, startedCallback, scaleUp);
4045        }
4046    }
4047
4048    @Override
4049    public void executeAppTransition() {
4050        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4051                "executeAppTransition()")) {
4052            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4053        }
4054
4055        synchronized(mWindowMap) {
4056            if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
4057                    new RuntimeException("here").fillInStackTrace());
4058            if (mAppTransition.isTransitionSet()) {
4059                mAppTransition.setReady();
4060                final long origId = Binder.clearCallingIdentity();
4061                try {
4062                    performLayoutAndPlaceSurfacesLocked();
4063                } finally {
4064                    Binder.restoreCallingIdentity(origId);
4065                }
4066            }
4067        }
4068    }
4069
4070    @Override
4071    public void setAppStartingWindow(IBinder token, String pkg,
4072            int theme, CompatibilityInfo compatInfo,
4073            CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
4074            int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
4075        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4076                "setAppStartingWindow()")) {
4077            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4078        }
4079
4080        synchronized(mWindowMap) {
4081            if (DEBUG_STARTING_WINDOW) Slog.v(
4082                    TAG, "setAppStartingWindow: token=" + token + " pkg=" + pkg
4083                    + " transferFrom=" + transferFrom);
4084
4085            AppWindowToken wtoken = findAppWindowToken(token);
4086            if (wtoken == null) {
4087                Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
4088                return;
4089            }
4090
4091            // If the display is frozen, we won't do anything until the
4092            // actual window is displayed so there is no reason to put in
4093            // the starting window.
4094            if (!okToDisplay()) {
4095                return;
4096            }
4097
4098            if (wtoken.startingData != null) {
4099                return;
4100            }
4101
4102            if (transferFrom != null) {
4103                AppWindowToken ttoken = findAppWindowToken(transferFrom);
4104                if (ttoken != null) {
4105                    WindowState startingWindow = ttoken.startingWindow;
4106                    if (startingWindow != null) {
4107                        if (mStartingIconInTransition) {
4108                            // In this case, the starting icon has already
4109                            // been displayed, so start letting windows get
4110                            // shown immediately without any more transitions.
4111                            mSkipAppTransitionAnimation = true;
4112                        }
4113                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4114                                "Moving existing starting " + startingWindow + " from " + ttoken
4115                                + " to " + wtoken);
4116                        final long origId = Binder.clearCallingIdentity();
4117
4118                        // Transfer the starting window over to the new
4119                        // token.
4120                        wtoken.startingData = ttoken.startingData;
4121                        wtoken.startingView = ttoken.startingView;
4122                        wtoken.startingDisplayed = ttoken.startingDisplayed;
4123                        ttoken.startingDisplayed = false;
4124                        wtoken.startingWindow = startingWindow;
4125                        wtoken.reportedVisible = ttoken.reportedVisible;
4126                        ttoken.startingData = null;
4127                        ttoken.startingView = null;
4128                        ttoken.startingWindow = null;
4129                        ttoken.startingMoved = true;
4130                        startingWindow.mToken = wtoken;
4131                        startingWindow.mRootToken = wtoken;
4132                        startingWindow.mAppToken = wtoken;
4133                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
4134
4135                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
4136                            Slog.v(TAG, "Removing starting window: " + startingWindow);
4137                        }
4138                        startingWindow.getWindowList().remove(startingWindow);
4139                        mWindowsChanged = true;
4140                        if (DEBUG_ADD_REMOVE) Slog.v(TAG,
4141                                "Removing starting " + startingWindow + " from " + ttoken);
4142                        ttoken.windows.remove(startingWindow);
4143                        ttoken.allAppWindows.remove(startingWindow);
4144                        addWindowToListInOrderLocked(startingWindow, true);
4145
4146                        // Propagate other interesting state between the
4147                        // tokens.  If the old token is displayed, we should
4148                        // immediately force the new one to be displayed.  If
4149                        // it is animating, we need to move that animation to
4150                        // the new one.
4151                        if (ttoken.allDrawn) {
4152                            wtoken.allDrawn = true;
4153                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
4154                        }
4155                        if (ttoken.firstWindowDrawn) {
4156                            wtoken.firstWindowDrawn = true;
4157                        }
4158                        if (!ttoken.hidden) {
4159                            wtoken.hidden = false;
4160                            wtoken.hiddenRequested = false;
4161                            wtoken.willBeHidden = false;
4162                        }
4163                        if (wtoken.clientHidden != ttoken.clientHidden) {
4164                            wtoken.clientHidden = ttoken.clientHidden;
4165                            wtoken.sendAppVisibilityToClients();
4166                        }
4167                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4168                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4169                        if (tAppAnimator.animation != null) {
4170                            wAppAnimator.animation = tAppAnimator.animation;
4171                            wAppAnimator.animating = tAppAnimator.animating;
4172                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
4173                            tAppAnimator.animation = null;
4174                            tAppAnimator.animLayerAdjustment = 0;
4175                            wAppAnimator.updateLayers();
4176                            tAppAnimator.updateLayers();
4177                        }
4178
4179                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4180                                true /*updateInputWindows*/);
4181                        getDefaultDisplayContentLocked().layoutNeeded = true;
4182                        performLayoutAndPlaceSurfacesLocked();
4183                        Binder.restoreCallingIdentity(origId);
4184                        return;
4185                    } else if (ttoken.startingData != null) {
4186                        // The previous app was getting ready to show a
4187                        // starting window, but hasn't yet done so.  Steal it!
4188                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
4189                                "Moving pending starting from " + ttoken
4190                                + " to " + wtoken);
4191                        wtoken.startingData = ttoken.startingData;
4192                        ttoken.startingData = null;
4193                        ttoken.startingMoved = true;
4194                        Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4195                        // Note: we really want to do sendMessageAtFrontOfQueue() because we
4196                        // want to process the message ASAP, before any other queued
4197                        // messages.
4198                        mH.sendMessageAtFrontOfQueue(m);
4199                        return;
4200                    }
4201                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
4202                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
4203                    if (tAppAnimator.thumbnail != null) {
4204                        // The old token is animating with a thumbnail, transfer
4205                        // that to the new token.
4206                        if (wAppAnimator.thumbnail != null) {
4207                            wAppAnimator.thumbnail.destroy();
4208                        }
4209                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
4210                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
4211                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
4212                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
4213                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
4214                        tAppAnimator.thumbnail = null;
4215                    }
4216                }
4217            }
4218
4219            // There is no existing starting window, and the caller doesn't
4220            // want us to create one, so that's it!
4221            if (!createIfNeeded) {
4222                return;
4223            }
4224
4225            // If this is a translucent window, then don't
4226            // show a starting window -- the current effect (a full-screen
4227            // opaque starting window that fades away to the real contents
4228            // when it is ready) does not work for this.
4229            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Checking theme of starting window: 0x"
4230                    + Integer.toHexString(theme));
4231            if (theme != 0) {
4232                AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
4233                        com.android.internal.R.styleable.Window, mCurrentUserId);
4234                if (ent == null) {
4235                    // Whoops!  App doesn't exist.  Um.  Okay.  We'll just
4236                    // pretend like we didn't see that.
4237                    return;
4238                }
4239                if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Translucent="
4240                        + ent.array.getBoolean(
4241                                com.android.internal.R.styleable.Window_windowIsTranslucent, false)
4242                        + " Floating="
4243                        + ent.array.getBoolean(
4244                                com.android.internal.R.styleable.Window_windowIsFloating, false)
4245                        + " ShowWallpaper="
4246                        + ent.array.getBoolean(
4247                                com.android.internal.R.styleable.Window_windowShowWallpaper, false));
4248                if (ent.array.getBoolean(
4249                        com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
4250                    return;
4251                }
4252                if (ent.array.getBoolean(
4253                        com.android.internal.R.styleable.Window_windowIsFloating, false)) {
4254                    return;
4255                }
4256                if (ent.array.getBoolean(
4257                        com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
4258                    if (mWallpaperTarget == null) {
4259                        // If this theme is requesting a wallpaper, and the wallpaper
4260                        // is not curently visible, then this effectively serves as
4261                        // an opaque window and our starting window transition animation
4262                        // can still work.  We just need to make sure the starting window
4263                        // is also showing the wallpaper.
4264                        windowFlags |= FLAG_SHOW_WALLPAPER;
4265                    } else {
4266                        return;
4267                    }
4268                }
4269            }
4270
4271            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
4272            mStartingIconInTransition = true;
4273            wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
4274                    labelRes, icon, logo, windowFlags);
4275            Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
4276            // Note: we really want to do sendMessageAtFrontOfQueue() because we
4277            // want to process the message ASAP, before any other queued
4278            // messages.
4279            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
4280            mH.sendMessageAtFrontOfQueue(m);
4281        }
4282    }
4283
4284    public void removeAppStartingWindow(IBinder token) {
4285        synchronized (mWindowMap) {
4286            AppWindowToken wtoken = mTokenMap.get(token).appWindowToken;
4287            if (wtoken.startingWindow != null) {
4288                scheduleRemoveStartingWindow(wtoken);
4289            }
4290        }
4291    }
4292
4293    @Override
4294    public void setAppWillBeHidden(IBinder token) {
4295        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4296                "setAppWillBeHidden()")) {
4297            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4298        }
4299
4300        AppWindowToken wtoken;
4301
4302        synchronized(mWindowMap) {
4303            wtoken = findAppWindowToken(token);
4304            if (wtoken == null) {
4305                Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
4306                return;
4307            }
4308            wtoken.willBeHidden = true;
4309        }
4310    }
4311
4312    public void setAppFullscreen(IBinder token, boolean toOpaque) {
4313        AppWindowToken atoken = findAppWindowToken(token);
4314        if (atoken != null) {
4315            atoken.appFullscreen = toOpaque;
4316            setWindowOpaque(token, toOpaque);
4317            requestTraversal();
4318        }
4319    }
4320
4321    public void setWindowOpaque(IBinder token, boolean isOpaque) {
4322        AppWindowToken wtoken = findAppWindowToken(token);
4323        if (wtoken != null) {
4324            WindowState win = wtoken.findMainWindow();
4325            if (win != null) {
4326                win.mWinAnimator.setOpaque(isOpaque);
4327            }
4328        }
4329    }
4330
4331    boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
4332            boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
4333        boolean delayed = false;
4334
4335        if (wtoken.clientHidden == visible) {
4336            wtoken.clientHidden = !visible;
4337            wtoken.sendAppVisibilityToClients();
4338        }
4339
4340        wtoken.willBeHidden = false;
4341        if (wtoken.hidden == visible) {
4342            boolean changed = false;
4343            if (DEBUG_APP_TRANSITIONS) Slog.v(
4344                TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
4345                + " performLayout=" + performLayout);
4346
4347            boolean runningAppAnimation = false;
4348
4349            if (transit != AppTransition.TRANSIT_UNSET) {
4350                if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
4351                    wtoken.mAppAnimator.animation = null;
4352                }
4353                if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
4354                    delayed = runningAppAnimation = true;
4355                }
4356                WindowState window = wtoken.findMainWindow();
4357                //TODO (multidisplay): Magnification is supported only for the default display.
4358                if (window != null && mAccessibilityController != null
4359                        && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
4360                    mAccessibilityController.onAppWindowTransitionLocked(window, transit);
4361                }
4362                changed = true;
4363            }
4364
4365            final int N = wtoken.allAppWindows.size();
4366            for (int i=0; i<N; i++) {
4367                WindowState win = wtoken.allAppWindows.get(i);
4368                if (win == wtoken.startingWindow) {
4369                    continue;
4370                }
4371
4372                //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
4373                //win.dump("  ");
4374                if (visible) {
4375                    if (!win.isVisibleNow()) {
4376                        if (!runningAppAnimation) {
4377                            win.mWinAnimator.applyAnimationLocked(
4378                                    WindowManagerPolicy.TRANSIT_ENTER, true);
4379                            //TODO (multidisplay): Magnification is supported only for the default
4380                            if (mAccessibilityController != null
4381                                    && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4382                                mAccessibilityController.onWindowTransitionLocked(win,
4383                                        WindowManagerPolicy.TRANSIT_ENTER);
4384                            }
4385                        }
4386                        changed = true;
4387                        final DisplayContent displayContent = win.getDisplayContent();
4388                        if (displayContent != null) {
4389                            displayContent.layoutNeeded = true;
4390                        }
4391                    }
4392                } else if (win.isVisibleNow()) {
4393                    if (!runningAppAnimation) {
4394                        win.mWinAnimator.applyAnimationLocked(
4395                                WindowManagerPolicy.TRANSIT_EXIT, false);
4396                        //TODO (multidisplay): Magnification is supported only for the default
4397                        if (mAccessibilityController != null
4398                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
4399                            mAccessibilityController.onWindowTransitionLocked(win,
4400                                    WindowManagerPolicy.TRANSIT_EXIT);
4401                        }
4402                    }
4403                    changed = true;
4404                    final DisplayContent displayContent = win.getDisplayContent();
4405                    if (displayContent != null) {
4406                        displayContent.layoutNeeded = true;
4407                    }
4408                }
4409            }
4410
4411            wtoken.hidden = wtoken.hiddenRequested = !visible;
4412            if (!visible) {
4413                unsetAppFreezingScreenLocked(wtoken, true, true);
4414            } else {
4415                // If we are being set visible, and the starting window is
4416                // not yet displayed, then make sure it doesn't get displayed.
4417                WindowState swin = wtoken.startingWindow;
4418                if (swin != null && !swin.isDrawnLw()) {
4419                    swin.mPolicyVisibility = false;
4420                    swin.mPolicyVisibilityAfterAnim = false;
4421                 }
4422            }
4423
4424            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
4425                      + ": hidden=" + wtoken.hidden + " hiddenRequested="
4426                      + wtoken.hiddenRequested);
4427
4428            if (changed) {
4429                mInputMonitor.setUpdateInputWindowsNeededLw();
4430                if (performLayout) {
4431                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4432                            false /*updateInputWindows*/);
4433                    performLayoutAndPlaceSurfacesLocked();
4434                }
4435                mInputMonitor.updateInputWindowsLw(false /*force*/);
4436            }
4437        }
4438
4439        if (wtoken.mAppAnimator.animation != null) {
4440            delayed = true;
4441        }
4442
4443        for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
4444            if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
4445                delayed = true;
4446            }
4447        }
4448
4449        return delayed;
4450    }
4451
4452    @Override
4453    public void setAppVisibility(IBinder token, boolean visible) {
4454        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4455                "setAppVisibility()")) {
4456            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4457        }
4458
4459        AppWindowToken wtoken;
4460
4461        synchronized(mWindowMap) {
4462            wtoken = findAppWindowToken(token);
4463            if (wtoken == null) {
4464                Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
4465                return;
4466            }
4467
4468            if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
4469                    token + ", visible=" + visible + "): " + mAppTransition +
4470                    " hidden=" + wtoken.hidden + " hiddenRequested=" +
4471                    wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
4472                            null : new RuntimeException("here").fillInStackTrace());
4473
4474            // If we are preparing an app transition, then delay changing
4475            // the visibility of this token until we execute that transition.
4476            if (okToDisplay() && mAppTransition.isTransitionSet()) {
4477                wtoken.hiddenRequested = !visible;
4478
4479                if (!wtoken.startingDisplayed) {
4480                    if (DEBUG_APP_TRANSITIONS) Slog.v(
4481                            TAG, "Setting dummy animation on: " + wtoken);
4482                    wtoken.mAppAnimator.setDummyAnimation();
4483                }
4484                mOpeningApps.remove(wtoken);
4485                mClosingApps.remove(wtoken);
4486                wtoken.waitingToShow = wtoken.waitingToHide = false;
4487                wtoken.inPendingTransaction = true;
4488                if (visible) {
4489                    mOpeningApps.add(wtoken);
4490                    wtoken.startingMoved = false;
4491                    wtoken.mEnteringAnimation = true;
4492
4493                    // If the token is currently hidden (should be the
4494                    // common case), then we need to set up to wait for
4495                    // its windows to be ready.
4496                    if (wtoken.hidden) {
4497                        wtoken.allDrawn = false;
4498                        wtoken.deferClearAllDrawn = false;
4499                        wtoken.waitingToShow = true;
4500
4501                        if (wtoken.clientHidden) {
4502                            // In the case where we are making an app visible
4503                            // but holding off for a transition, we still need
4504                            // to tell the client to make its windows visible so
4505                            // they get drawn.  Otherwise, we will wait on
4506                            // performing the transition until all windows have
4507                            // been drawn, they never will be, and we are sad.
4508                            wtoken.clientHidden = false;
4509                            wtoken.sendAppVisibilityToClients();
4510                        }
4511                    }
4512                } else {
4513                    mClosingApps.add(wtoken);
4514                    wtoken.mEnteringAnimation = false;
4515
4516                    // If the token is currently visible (should be the
4517                    // common case), then set up to wait for it to be hidden.
4518                    if (!wtoken.hidden) {
4519                        wtoken.waitingToHide = true;
4520                    }
4521                }
4522                if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
4523                    // We're launchingBehind, add the launching activity to mOpeningApps.
4524                    final WindowState win =
4525                            findFocusedWindowLocked(getDefaultDisplayContentLocked());
4526                    if (win != null) {
4527                        final AppWindowToken focusedToken = win.mAppToken;
4528                        if (focusedToken != null) {
4529                            if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " +
4530                                    " adding " + focusedToken + " to mOpeningApps");
4531                            // Force animation to be loaded.
4532                            focusedToken.hidden = true;
4533                            mOpeningApps.add(focusedToken);
4534                        }
4535                    }
4536                }
4537                return;
4538            }
4539
4540            final long origId = Binder.clearCallingIdentity();
4541            setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
4542                    true, wtoken.voiceInteraction);
4543            wtoken.updateReportedVisibilityLocked();
4544            Binder.restoreCallingIdentity(origId);
4545        }
4546    }
4547
4548    void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
4549            boolean unfreezeSurfaceNow, boolean force) {
4550        if (wtoken.mAppAnimator.freezingScreen) {
4551            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
4552                    + " force=" + force);
4553            final int N = wtoken.allAppWindows.size();
4554            boolean unfrozeWindows = false;
4555            for (int i=0; i<N; i++) {
4556                WindowState w = wtoken.allAppWindows.get(i);
4557                if (w.mAppFreezing) {
4558                    w.mAppFreezing = false;
4559                    if (w.mHasSurface && !w.mOrientationChanging) {
4560                        if (DEBUG_ORIENTATION) Slog.v(TAG, "set mOrientationChanging of " + w);
4561                        w.mOrientationChanging = true;
4562                        mInnerFields.mOrientationChangeComplete = false;
4563                    }
4564                    w.mLastFreezeDuration = 0;
4565                    unfrozeWindows = true;
4566                    final DisplayContent displayContent = w.getDisplayContent();
4567                    if (displayContent != null) {
4568                        displayContent.layoutNeeded = true;
4569                    }
4570                }
4571            }
4572            if (force || unfrozeWindows) {
4573                if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
4574                wtoken.mAppAnimator.freezingScreen = false;
4575                wtoken.mAppAnimator.lastFreezeDuration = (int)(SystemClock.elapsedRealtime()
4576                        - mDisplayFreezeTime);
4577                mAppsFreezingScreen--;
4578                mLastFinishedFreezeSource = wtoken;
4579            }
4580            if (unfreezeSurfaceNow) {
4581                if (unfrozeWindows) {
4582                    performLayoutAndPlaceSurfacesLocked();
4583                }
4584                stopFreezingDisplayLocked();
4585            }
4586        }
4587    }
4588
4589    private void startAppFreezingScreenLocked(AppWindowToken wtoken) {
4590        if (DEBUG_ORIENTATION) {
4591            RuntimeException e = null;
4592            if (!HIDE_STACK_CRAWLS) {
4593                e = new RuntimeException();
4594                e.fillInStackTrace();
4595            }
4596            Slog.i(TAG, "Set freezing of " + wtoken.appToken
4597                    + ": hidden=" + wtoken.hidden + " freezing="
4598                    + wtoken.mAppAnimator.freezingScreen, e);
4599        }
4600        if (!wtoken.hiddenRequested) {
4601            if (!wtoken.mAppAnimator.freezingScreen) {
4602                wtoken.mAppAnimator.freezingScreen = true;
4603                wtoken.mAppAnimator.lastFreezeDuration = 0;
4604                mAppsFreezingScreen++;
4605                if (mAppsFreezingScreen == 1) {
4606                    startFreezingDisplayLocked(false, 0, 0);
4607                    mH.removeMessages(H.APP_FREEZE_TIMEOUT);
4608                    mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 5000);
4609                }
4610            }
4611            final int N = wtoken.allAppWindows.size();
4612            for (int i=0; i<N; i++) {
4613                WindowState w = wtoken.allAppWindows.get(i);
4614                w.mAppFreezing = true;
4615            }
4616        }
4617    }
4618
4619    @Override
4620    public void startAppFreezingScreen(IBinder token, int configChanges) {
4621        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4622                "setAppFreezingScreen()")) {
4623            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4624        }
4625
4626        synchronized(mWindowMap) {
4627            if (configChanges == 0 && okToDisplay()) {
4628                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
4629                return;
4630            }
4631
4632            AppWindowToken wtoken = findAppWindowToken(token);
4633            if (wtoken == null || wtoken.appToken == null) {
4634                Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
4635                return;
4636            }
4637            final long origId = Binder.clearCallingIdentity();
4638            startAppFreezingScreenLocked(wtoken);
4639            Binder.restoreCallingIdentity(origId);
4640        }
4641    }
4642
4643    @Override
4644    public void stopAppFreezingScreen(IBinder token, boolean force) {
4645        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4646                "setAppFreezingScreen()")) {
4647            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4648        }
4649
4650        synchronized(mWindowMap) {
4651            AppWindowToken wtoken = findAppWindowToken(token);
4652            if (wtoken == null || wtoken.appToken == null) {
4653                return;
4654            }
4655            final long origId = Binder.clearCallingIdentity();
4656            if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
4657                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
4658            unsetAppFreezingScreenLocked(wtoken, true, force);
4659            Binder.restoreCallingIdentity(origId);
4660        }
4661    }
4662
4663    void removeAppFromTaskLocked(AppWindowToken wtoken) {
4664        wtoken.removeAllWindows();
4665
4666        final Task task = mTaskIdToTask.get(wtoken.groupId);
4667        if (task != null) {
4668            if (!task.removeAppToken(wtoken)) {
4669                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
4670            }
4671        }
4672    }
4673
4674    @Override
4675    public void removeAppToken(IBinder token) {
4676        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4677                "removeAppToken()")) {
4678            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
4679        }
4680
4681        AppWindowToken wtoken = null;
4682        AppWindowToken startingToken = null;
4683        boolean delayed = false;
4684
4685        final long origId = Binder.clearCallingIdentity();
4686        synchronized(mWindowMap) {
4687            WindowToken basewtoken = mTokenMap.remove(token);
4688            Slog.w("BadTokenDebug", "removeAppToke: Removing token=" + token + " removed=" + basewtoken);
4689            if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
4690                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
4691                delayed = setTokenVisibilityLocked(wtoken, null, false,
4692                        AppTransition.TRANSIT_UNSET, true, wtoken.voiceInteraction);
4693                wtoken.inPendingTransaction = false;
4694                mOpeningApps.remove(wtoken);
4695                wtoken.waitingToShow = false;
4696                if (mClosingApps.contains(wtoken)) {
4697                    delayed = true;
4698                } else if (mAppTransition.isTransitionSet()) {
4699                    mClosingApps.add(wtoken);
4700                    wtoken.waitingToHide = true;
4701                    delayed = true;
4702                }
4703                if (DEBUG_APP_TRANSITIONS) Slog.v(
4704                        TAG, "Removing app " + wtoken + " delayed=" + delayed
4705                        + " animation=" + wtoken.mAppAnimator.animation
4706                        + " animating=" + wtoken.mAppAnimator.animating);
4707                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
4708                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
4709                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
4710                if (delayed) {
4711                    // set the token aside because it has an active animation to be finished
4712                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
4713                            "removeAppToken make exiting: " + wtoken);
4714                    stack.mExitingAppTokens.add(wtoken);
4715                    wtoken.mDeferRemoval = true;
4716                } else {
4717                    // Make sure there is no animation running on this token,
4718                    // so any windows associated with it will be removed as
4719                    // soon as their animations are complete
4720                    wtoken.mAppAnimator.clearAnimation();
4721                    wtoken.mAppAnimator.animating = false;
4722                    removeAppFromTaskLocked(wtoken);
4723                }
4724
4725                wtoken.removed = true;
4726                if (wtoken.startingData != null) {
4727                    startingToken = wtoken;
4728                }
4729                unsetAppFreezingScreenLocked(wtoken, true, true);
4730                if (mFocusedApp == wtoken) {
4731                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Removing focused app token:" + wtoken);
4732                    mFocusedApp = null;
4733                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
4734                    mInputMonitor.setFocusedAppLw(null);
4735                }
4736            } else {
4737                Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
4738            }
4739
4740            if (!delayed && wtoken != null) {
4741                wtoken.updateReportedVisibilityLocked();
4742            }
4743        }
4744        Binder.restoreCallingIdentity(origId);
4745
4746        // Will only remove if startingToken non null.
4747        scheduleRemoveStartingWindow(startingToken);
4748    }
4749
4750    void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
4751        if (wtoken != null && wtoken.startingWindow != null) {
4752            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
4753                    ": Schedule remove starting " + wtoken + (wtoken != null ?
4754                    " startingWindow=" + wtoken.startingWindow : ""));
4755            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
4756            mH.sendMessage(m);
4757        }
4758    }
4759
4760    private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4761        WindowList windows = token.windows;
4762        final int NW = windows.size();
4763        if (NW > 0) {
4764            mWindowsChanged = true;
4765        }
4766        for (int i = 0; i < NW; i++) {
4767            WindowState win = windows.get(i);
4768            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
4769            win.getWindowList().remove(win);
4770            int j = win.mChildWindows.size();
4771            while (j > 0) {
4772                j--;
4773                WindowState cwin = win.mChildWindows.get(j);
4774                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
4775                        "Tmp removing child window " + cwin);
4776                cwin.getWindowList().remove(cwin);
4777            }
4778        }
4779        return NW > 0;
4780    }
4781
4782    void dumpAppTokensLocked() {
4783        final int numStacks = mStackIdToStack.size();
4784        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
4785            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
4786            Slog.v(TAG, "  Stack #" + stack.mStackId + " tasks from bottom to top:");
4787            final ArrayList<Task> tasks = stack.getTasks();
4788            final int numTasks = tasks.size();
4789            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4790                final Task task = tasks.get(taskNdx);
4791                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
4792                AppTokenList tokens = task.mAppTokens;
4793                final int numTokens = tokens.size();
4794                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4795                    Slog.v(TAG, "      activity #" + tokenNdx + ": " + tokens.get(tokenNdx).token);
4796                }
4797            }
4798        }
4799    }
4800
4801    void dumpWindowsLocked() {
4802        final int numDisplays = mDisplayContents.size();
4803        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
4804            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
4805            Slog.v(TAG, " Display #" + displayContent.getDisplayId());
4806            final WindowList windows = displayContent.getWindowList();
4807            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
4808                Slog.v(TAG, "  #" + winNdx + ": " + windows.get(winNdx));
4809            }
4810        }
4811    }
4812
4813    private int findAppWindowInsertionPointLocked(AppWindowToken target) {
4814        final int taskId = target.groupId;
4815        Task targetTask = mTaskIdToTask.get(taskId);
4816        if (targetTask == null) {
4817            Slog.w(TAG, "findAppWindowInsertionPointLocked: no Task for " + target + " taskId="
4818                    + taskId);
4819            return 0;
4820        }
4821        DisplayContent displayContent = targetTask.getDisplayContent();
4822        if (displayContent == null) {
4823            Slog.w(TAG, "findAppWindowInsertionPointLocked: no DisplayContent for " + target);
4824            return 0;
4825        }
4826        final WindowList windows = displayContent.getWindowList();
4827        final int NW = windows.size();
4828
4829        boolean found = false;
4830        final ArrayList<Task> tasks = displayContent.getTasks();
4831        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
4832            final Task task = tasks.get(taskNdx);
4833            if (!found && task.taskId != taskId) {
4834                continue;
4835            }
4836            AppTokenList tokens = task.mAppTokens;
4837            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4838                final AppWindowToken wtoken = tokens.get(tokenNdx);
4839                if (!found && wtoken == target) {
4840                    found = true;
4841                }
4842                if (found) {
4843                    // Find the first app token below the new position that has
4844                    // a window displayed.
4845                    if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
4846                    if (wtoken.sendingToBottom) {
4847                        if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
4848                        continue;
4849                    }
4850                    for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
4851                        WindowState win = wtoken.windows.get(i);
4852                        for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
4853                            WindowState cwin = win.mChildWindows.get(j);
4854                            if (cwin.mSubLayer >= 0) {
4855                                for (int pos = NW - 1; pos >= 0; pos--) {
4856                                    if (windows.get(pos) == cwin) {
4857                                        if (DEBUG_REORDER) Slog.v(TAG,
4858                                                "Found child win @" + (pos + 1));
4859                                        return pos + 1;
4860                                    }
4861                                }
4862                            }
4863                        }
4864                        for (int pos = NW - 1; pos >= 0; pos--) {
4865                            if (windows.get(pos) == win) {
4866                                if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
4867                                return pos + 1;
4868                            }
4869                        }
4870                    }
4871                }
4872            }
4873        }
4874        // Never put an app window underneath wallpaper.
4875        for (int pos = NW - 1; pos >= 0; pos--) {
4876            if (windows.get(pos).mIsWallpaper) {
4877                if (DEBUG_REORDER) Slog.v(TAG, "Found wallpaper @" + pos);
4878                return pos + 1;
4879            }
4880        }
4881        return 0;
4882    }
4883
4884    private final int reAddWindowLocked(int index, WindowState win) {
4885        final WindowList windows = win.getWindowList();
4886        final int NCW = win.mChildWindows.size();
4887        boolean added = false;
4888        for (int j=0; j<NCW; j++) {
4889            WindowState cwin = win.mChildWindows.get(j);
4890            if (!added && cwin.mSubLayer >= 0) {
4891                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
4892                        + index + ": " + cwin);
4893                win.mRebuilding = false;
4894                windows.add(index, win);
4895                index++;
4896                added = true;
4897            }
4898            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4899                    + index + ": " + cwin);
4900            cwin.mRebuilding = false;
4901            windows.add(index, cwin);
4902            index++;
4903        }
4904        if (!added) {
4905            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
4906                    + index + ": " + win);
4907            win.mRebuilding = false;
4908            windows.add(index, win);
4909            index++;
4910        }
4911        mWindowsChanged = true;
4912        return index;
4913    }
4914
4915    private final int reAddAppWindowsLocked(final DisplayContent displayContent, int index,
4916                                            WindowToken token) {
4917        final int NW = token.windows.size();
4918        for (int i=0; i<NW; i++) {
4919            final WindowState win = token.windows.get(i);
4920            final DisplayContent winDisplayContent = win.getDisplayContent();
4921            if (winDisplayContent == displayContent || winDisplayContent == null) {
4922                win.mDisplayContent = displayContent;
4923                index = reAddWindowLocked(index, win);
4924            }
4925        }
4926        return index;
4927    }
4928
4929    void tmpRemoveTaskWindowsLocked(Task task) {
4930        AppTokenList tokens = task.mAppTokens;
4931        for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
4932            tmpRemoveAppWindowsLocked(tokens.get(tokenNdx));
4933        }
4934    }
4935
4936    void moveStackWindowsLocked(DisplayContent displayContent) {
4937        // First remove all of the windows from the list.
4938        final ArrayList<Task> tasks = displayContent.getTasks();
4939        final int numTasks = tasks.size();
4940        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4941            tmpRemoveTaskWindowsLocked(tasks.get(taskNdx));
4942        }
4943
4944        // And now add them back at the correct place.
4945        // Where to start adding?
4946        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
4947            AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
4948            final int numTokens = tokens.size();
4949            if (numTokens == 0) {
4950                continue;
4951            }
4952            int pos = findAppWindowInsertionPointLocked(tokens.get(0));
4953            for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
4954                final AppWindowToken wtoken = tokens.get(tokenNdx);
4955                if (wtoken != null) {
4956                    final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
4957                    if (newPos != pos) {
4958                        displayContent.layoutNeeded = true;
4959                    }
4960                    pos = newPos;
4961                }
4962            }
4963        }
4964
4965        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4966                false /*updateInputWindows*/)) {
4967            assignLayersLocked(displayContent.getWindowList());
4968        }
4969
4970        mInputMonitor.setUpdateInputWindowsNeededLw();
4971        performLayoutAndPlaceSurfacesLocked();
4972        mInputMonitor.updateInputWindowsLw(false /*force*/);
4973
4974        //dump();
4975    }
4976
4977    public void moveTaskToTop(int taskId) {
4978        final long origId = Binder.clearCallingIdentity();
4979        try {
4980            synchronized(mWindowMap) {
4981                Task task = mTaskIdToTask.get(taskId);
4982                if (task == null) {
4983                    // Normal behavior, addAppToken will be called next and task will be created.
4984                    return;
4985                }
4986                final TaskStack stack = task.mStack;
4987                final DisplayContent displayContent = task.getDisplayContent();
4988                displayContent.moveStack(stack, true);
4989                if (displayContent.isDefaultDisplay) {
4990                    final TaskStack homeStack = displayContent.getHomeStack();
4991                    if (homeStack != stack) {
4992                        // When a non-home stack moves to the top, the home stack moves to the
4993                        // bottom.
4994                        displayContent.moveStack(homeStack, false);
4995                    }
4996                }
4997                stack.moveTaskToTop(task);
4998            }
4999        } finally {
5000            Binder.restoreCallingIdentity(origId);
5001        }
5002    }
5003
5004    public void moveTaskToBottom(int taskId) {
5005        final long origId = Binder.clearCallingIdentity();
5006        try {
5007            synchronized(mWindowMap) {
5008                Task task = mTaskIdToTask.get(taskId);
5009                if (task == null) {
5010                    Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
5011                            + " not found in mTaskIdToTask");
5012                    return;
5013                }
5014                final TaskStack stack = task.mStack;
5015                stack.moveTaskToBottom(task);
5016                moveStackWindowsLocked(stack.getDisplayContent());
5017            }
5018        } finally {
5019            Binder.restoreCallingIdentity(origId);
5020        }
5021    }
5022
5023    /**
5024     * Create a new TaskStack and place it on a DisplayContent.
5025     * @param stackId The unique identifier of the new stack.
5026     * @param displayId The unique identifier of the DisplayContent.
5027     */
5028    public void attachStack(int stackId, int displayId) {
5029        final long origId = Binder.clearCallingIdentity();
5030        try {
5031            synchronized (mWindowMap) {
5032                final DisplayContent displayContent = mDisplayContents.get(displayId);
5033                if (displayContent != null) {
5034                    TaskStack stack = mStackIdToStack.get(stackId);
5035                    if (stack == null) {
5036                        if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
5037                        stack = new TaskStack(this, stackId);
5038                        mStackIdToStack.put(stackId, stack);
5039                    }
5040                    stack.attachDisplayContent(displayContent);
5041                    displayContent.attachStack(stack);
5042                    moveStackWindowsLocked(displayContent);
5043                    final WindowList windows = displayContent.getWindowList();
5044                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
5045                        windows.get(winNdx).reportResized();
5046                    }
5047                }
5048            }
5049        } finally {
5050            Binder.restoreCallingIdentity(origId);
5051        }
5052    }
5053
5054    void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
5055        displayContent.detachStack(stack);
5056        stack.detachDisplay();
5057    }
5058
5059    public void detachStack(int stackId) {
5060        synchronized (mWindowMap) {
5061            TaskStack stack = mStackIdToStack.get(stackId);
5062            if (stack != null) {
5063                final DisplayContent displayContent = stack.getDisplayContent();
5064                if (displayContent != null) {
5065                    if (stack.isAnimating()) {
5066                        stack.mDeferDetach = true;
5067                        return;
5068                    }
5069                    detachStackLocked(displayContent, stack);
5070                }
5071            }
5072        }
5073    }
5074
5075    public void removeStack(int stackId) {
5076        mStackIdToStack.remove(stackId);
5077    }
5078
5079    void removeTaskLocked(Task task) {
5080        final int taskId = task.taskId;
5081        final TaskStack stack = task.mStack;
5082        if (stack.isAnimating()) {
5083            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
5084            task.mDeferRemoval = true;
5085            return;
5086        }
5087        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
5088        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
5089        task.mDeferRemoval = false;
5090        task.mStack.removeTask(task);
5091        mTaskIdToTask.delete(task.taskId);
5092    }
5093
5094    public void removeTask(int taskId) {
5095        synchronized (mWindowMap) {
5096            Task task = mTaskIdToTask.get(taskId);
5097            if (task == null) {
5098                if (DEBUG_STACK) Slog.i(TAG, "removeTask: could not find taskId=" + taskId);
5099                return;
5100            }
5101            removeTaskLocked(task);
5102        }
5103    }
5104
5105    public void addTask(int taskId, int stackId, boolean toTop) {
5106        synchronized (mWindowMap) {
5107            if (DEBUG_STACK) Slog.i(TAG, "addTask: adding taskId=" + taskId
5108                    + " to " + (toTop ? "top" : "bottom"));
5109            Task task = mTaskIdToTask.get(taskId);
5110            if (task == null) {
5111                return;
5112            }
5113            TaskStack stack = mStackIdToStack.get(stackId);
5114            stack.addTask(task, toTop);
5115            final DisplayContent displayContent = stack.getDisplayContent();
5116            displayContent.layoutNeeded = true;
5117            performLayoutAndPlaceSurfacesLocked();
5118        }
5119    }
5120
5121    public void resizeStack(int stackId, Rect bounds) {
5122        synchronized (mWindowMap) {
5123            final TaskStack stack = mStackIdToStack.get(stackId);
5124            if (stack == null) {
5125                throw new IllegalArgumentException("resizeStack: stackId " + stackId
5126                        + " not found.");
5127            }
5128            if (stack.setBounds(bounds)) {
5129                stack.resizeWindows();
5130                stack.getDisplayContent().layoutNeeded = true;
5131                performLayoutAndPlaceSurfacesLocked();
5132            }
5133        }
5134    }
5135
5136    public void getStackBounds(int stackId, Rect bounds) {
5137        final TaskStack stack = mStackIdToStack.get(stackId);
5138        if (stack != null) {
5139            stack.getBounds(bounds);
5140            return;
5141        }
5142        bounds.setEmpty();
5143    }
5144
5145    // -------------------------------------------------------------
5146    // Misc IWindowSession methods
5147    // -------------------------------------------------------------
5148
5149    @Override
5150    public void startFreezingScreen(int exitAnim, int enterAnim) {
5151        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5152                "startFreezingScreen()")) {
5153            throw new SecurityException("Requires FREEZE_SCREEN permission");
5154        }
5155
5156        synchronized(mWindowMap) {
5157            if (!mClientFreezingScreen) {
5158                mClientFreezingScreen = true;
5159                final long origId = Binder.clearCallingIdentity();
5160                try {
5161                    startFreezingDisplayLocked(false, exitAnim, enterAnim);
5162                    mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
5163                    mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
5164                } finally {
5165                    Binder.restoreCallingIdentity(origId);
5166                }
5167            }
5168        }
5169    }
5170
5171    @Override
5172    public void stopFreezingScreen() {
5173        if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
5174                "stopFreezingScreen()")) {
5175            throw new SecurityException("Requires FREEZE_SCREEN permission");
5176        }
5177
5178        synchronized(mWindowMap) {
5179            if (mClientFreezingScreen) {
5180                mClientFreezingScreen = false;
5181                mLastFinishedFreezeSource = "client";
5182                final long origId = Binder.clearCallingIdentity();
5183                try {
5184                    stopFreezingDisplayLocked();
5185                } finally {
5186                    Binder.restoreCallingIdentity(origId);
5187                }
5188            }
5189        }
5190    }
5191
5192    @Override
5193    public void disableKeyguard(IBinder token, String tag) {
5194        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5195            != PackageManager.PERMISSION_GRANTED) {
5196            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5197        }
5198
5199        if (token == null) {
5200            throw new IllegalArgumentException("token == null");
5201        }
5202
5203        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5204                KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
5205    }
5206
5207    @Override
5208    public void reenableKeyguard(IBinder token) {
5209        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5210            != PackageManager.PERMISSION_GRANTED) {
5211            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5212        }
5213
5214        if (token == null) {
5215            throw new IllegalArgumentException("token == null");
5216        }
5217
5218        mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
5219                KeyguardDisableHandler.KEYGUARD_REENABLE, token));
5220    }
5221
5222    /**
5223     * @see android.app.KeyguardManager#exitKeyguardSecurely
5224     */
5225    @Override
5226    public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
5227        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5228            != PackageManager.PERMISSION_GRANTED) {
5229            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5230        }
5231
5232        if (callback == null) {
5233            throw new IllegalArgumentException("callback == null");
5234        }
5235
5236        mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
5237            @Override
5238            public void onKeyguardExitResult(boolean success) {
5239                try {
5240                    callback.onKeyguardExitResult(success);
5241                } catch (RemoteException e) {
5242                    // Client has died, we don't care.
5243                }
5244            }
5245        });
5246    }
5247
5248    @Override
5249    public boolean inKeyguardRestrictedInputMode() {
5250        return mPolicy.inKeyguardRestrictedKeyInputMode();
5251    }
5252
5253    @Override
5254    public boolean isKeyguardLocked() {
5255        return mPolicy.isKeyguardLocked();
5256    }
5257
5258    @Override
5259    public boolean isKeyguardSecure() {
5260        return mPolicy.isKeyguardSecure();
5261    }
5262
5263    @Override
5264    public void dismissKeyguard() {
5265        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5266                != PackageManager.PERMISSION_GRANTED) {
5267            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5268        }
5269        synchronized(mWindowMap) {
5270            mPolicy.dismissKeyguardLw();
5271        }
5272    }
5273
5274    @Override
5275    public void keyguardGoingAway(boolean disableWindowAnimations,
5276            boolean keyguardGoingToNotificationShade) {
5277        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
5278                != PackageManager.PERMISSION_GRANTED) {
5279            throw new SecurityException("Requires DISABLE_KEYGUARD permission");
5280        }
5281        synchronized (mWindowMap) {
5282            mAnimator.mKeyguardGoingAway = true;
5283            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
5284            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
5285            requestTraversalLocked();
5286        }
5287    }
5288
5289    public void keyguardWaitingForActivityDrawn() {
5290        synchronized (mWindowMap) {
5291            mKeyguardWaitingForActivityDrawn = true;
5292        }
5293    }
5294
5295    public void notifyActivityDrawnForKeyguard() {
5296        synchronized (mWindowMap) {
5297            if (mKeyguardWaitingForActivityDrawn) {
5298                mPolicy.notifyActivityDrawnForKeyguardLw();
5299                mKeyguardWaitingForActivityDrawn = false;
5300            }
5301        }
5302    }
5303
5304    void showGlobalActions() {
5305        mPolicy.showGlobalActions();
5306    }
5307
5308    @Override
5309    public void closeSystemDialogs(String reason) {
5310        synchronized(mWindowMap) {
5311            final int numDisplays = mDisplayContents.size();
5312            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5313                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5314                final int numWindows = windows.size();
5315                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5316                    final WindowState w = windows.get(winNdx);
5317                    if (w.mHasSurface) {
5318                        try {
5319                            w.mClient.closeSystemDialogs(reason);
5320                        } catch (RemoteException e) {
5321                        }
5322                    }
5323                }
5324            }
5325        }
5326    }
5327
5328    static float fixScale(float scale) {
5329        if (scale < 0) scale = 0;
5330        else if (scale > 20) scale = 20;
5331        return Math.abs(scale);
5332    }
5333
5334    @Override
5335    public void setAnimationScale(int which, float scale) {
5336        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5337                "setAnimationScale()")) {
5338            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5339        }
5340
5341        scale = fixScale(scale);
5342        switch (which) {
5343            case 0: mWindowAnimationScaleSetting = scale; break;
5344            case 1: mTransitionAnimationScaleSetting = scale; break;
5345            case 2: mAnimatorDurationScaleSetting = scale; break;
5346        }
5347
5348        // Persist setting
5349        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5350    }
5351
5352    @Override
5353    public void setAnimationScales(float[] scales) {
5354        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
5355                "setAnimationScale()")) {
5356            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
5357        }
5358
5359        if (scales != null) {
5360            if (scales.length >= 1) {
5361                mWindowAnimationScaleSetting = fixScale(scales[0]);
5362            }
5363            if (scales.length >= 2) {
5364                mTransitionAnimationScaleSetting = fixScale(scales[1]);
5365            }
5366            if (scales.length >= 3) {
5367                mAnimatorDurationScaleSetting = fixScale(scales[2]);
5368                dispatchNewAnimatorScaleLocked(null);
5369            }
5370        }
5371
5372        // Persist setting
5373        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
5374    }
5375
5376    private void setAnimatorDurationScale(float scale) {
5377        mAnimatorDurationScaleSetting = scale;
5378        ValueAnimator.setDurationScale(scale);
5379    }
5380
5381    public float getWindowAnimationScaleLocked() {
5382        return mAnimationsDisabled ? 0 : mWindowAnimationScaleSetting;
5383    }
5384
5385    public float getTransitionAnimationScaleLocked() {
5386        return mAnimationsDisabled ? 0 : mTransitionAnimationScaleSetting;
5387    }
5388
5389    @Override
5390    public float getAnimationScale(int which) {
5391        switch (which) {
5392            case 0: return mWindowAnimationScaleSetting;
5393            case 1: return mTransitionAnimationScaleSetting;
5394            case 2: return mAnimatorDurationScaleSetting;
5395        }
5396        return 0;
5397    }
5398
5399    @Override
5400    public float[] getAnimationScales() {
5401        return new float[] { mWindowAnimationScaleSetting, mTransitionAnimationScaleSetting,
5402                mAnimatorDurationScaleSetting };
5403    }
5404
5405    @Override
5406    public float getCurrentAnimatorScale() {
5407        synchronized(mWindowMap) {
5408            return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
5409        }
5410    }
5411
5412    void dispatchNewAnimatorScaleLocked(Session session) {
5413        mH.obtainMessage(H.NEW_ANIMATOR_SCALE, session).sendToTarget();
5414    }
5415
5416    @Override
5417    public void registerPointerEventListener(PointerEventListener listener) {
5418        mPointerEventDispatcher.registerInputEventListener(listener);
5419    }
5420
5421    @Override
5422    public void unregisterPointerEventListener(PointerEventListener listener) {
5423        mPointerEventDispatcher.unregisterInputEventListener(listener);
5424    }
5425
5426    // Called by window manager policy. Not exposed externally.
5427    @Override
5428    public int getLidState() {
5429        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
5430                InputManagerService.SW_LID);
5431        if (sw > 0) {
5432            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
5433            return LID_CLOSED;
5434        } else if (sw == 0) {
5435            // Switch state: AKEY_STATE_UP.
5436            return LID_OPEN;
5437        } else {
5438            // Switch state: AKEY_STATE_UNKNOWN.
5439            return LID_ABSENT;
5440        }
5441    }
5442
5443    // Called by window manager policy.  Not exposed externally.
5444    @Override
5445    public void switchKeyboardLayout(int deviceId, int direction) {
5446        mInputManager.switchKeyboardLayout(deviceId, direction);
5447    }
5448
5449    // Called by window manager policy.  Not exposed externally.
5450    @Override
5451    public void shutdown(boolean confirm) {
5452        ShutdownThread.shutdown(mContext, confirm);
5453    }
5454
5455    // Called by window manager policy.  Not exposed externally.
5456    @Override
5457    public void rebootSafeMode(boolean confirm) {
5458        ShutdownThread.rebootSafeMode(mContext, confirm);
5459    }
5460
5461    public void setCurrentProfileIds(final int[] currentProfileIds) {
5462        synchronized (mWindowMap) {
5463            mCurrentProfileIds = currentProfileIds;
5464        }
5465    }
5466
5467    public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
5468        synchronized (mWindowMap) {
5469            mCurrentUserId = newUserId;
5470            mCurrentProfileIds = currentProfileIds;
5471            mAppTransition.setCurrentUser(newUserId);
5472            mPolicy.setCurrentUserLw(newUserId);
5473
5474            // Hide windows that should not be seen by the new user.
5475            final int numDisplays = mDisplayContents.size();
5476            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5477                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
5478                displayContent.switchUserStacks(newUserId);
5479                rebuildAppWindowListLocked(displayContent);
5480            }
5481            performLayoutAndPlaceSurfacesLocked();
5482        }
5483    }
5484
5485    /* Called by WindowState */
5486    boolean isCurrentProfileLocked(int userId) {
5487        if (userId == mCurrentUserId) return true;
5488        for (int i = 0; i < mCurrentProfileIds.length; i++) {
5489            if (mCurrentProfileIds[i] == userId) return true;
5490        }
5491        return false;
5492    }
5493
5494    public void enableScreenAfterBoot() {
5495        synchronized(mWindowMap) {
5496            if (DEBUG_BOOT) {
5497                RuntimeException here = new RuntimeException("here");
5498                here.fillInStackTrace();
5499                Slog.i(TAG, "enableScreenAfterBoot: mDisplayEnabled=" + mDisplayEnabled
5500                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5501                        + " mShowingBootMessages=" + mShowingBootMessages
5502                        + " mSystemBooted=" + mSystemBooted, here);
5503            }
5504            if (mSystemBooted) {
5505                return;
5506            }
5507            mSystemBooted = true;
5508            hideBootMessagesLocked();
5509            // If the screen still doesn't come up after 30 seconds, give
5510            // up and turn it on.
5511            mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30*1000);
5512        }
5513
5514        mPolicy.systemBooted();
5515
5516        performEnableScreen();
5517    }
5518
5519    @Override
5520    public void enableScreenIfNeeded() {
5521        synchronized (mWindowMap) {
5522            enableScreenIfNeededLocked();
5523        }
5524    }
5525
5526    void enableScreenIfNeededLocked() {
5527        if (DEBUG_BOOT) {
5528            RuntimeException here = new RuntimeException("here");
5529            here.fillInStackTrace();
5530            Slog.i(TAG, "enableScreenIfNeededLocked: mDisplayEnabled=" + mDisplayEnabled
5531                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5532                    + " mShowingBootMessages=" + mShowingBootMessages
5533                    + " mSystemBooted=" + mSystemBooted, here);
5534        }
5535        if (mDisplayEnabled) {
5536            return;
5537        }
5538        if (!mSystemBooted && !mShowingBootMessages) {
5539            return;
5540        }
5541        mH.sendEmptyMessage(H.ENABLE_SCREEN);
5542    }
5543
5544    public void performBootTimeout() {
5545        synchronized(mWindowMap) {
5546            if (mDisplayEnabled) {
5547                return;
5548            }
5549            Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled");
5550            mForceDisplayEnabled = true;
5551        }
5552        performEnableScreen();
5553    }
5554
5555    public void performEnableScreen() {
5556        synchronized(mWindowMap) {
5557            if (DEBUG_BOOT) {
5558                RuntimeException here = new RuntimeException("here");
5559                here.fillInStackTrace();
5560                Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
5561                        + " mForceDisplayEnabled=" + mForceDisplayEnabled
5562                        + " mShowingBootMessages=" + mShowingBootMessages
5563                        + " mSystemBooted=" + mSystemBooted
5564                        + " mOnlyCore=" + mOnlyCore, here);
5565            }
5566            if (mDisplayEnabled) {
5567                return;
5568            }
5569            if (!mSystemBooted && !mShowingBootMessages) {
5570                return;
5571            }
5572
5573            if (!mForceDisplayEnabled) {
5574                // Don't enable the screen until all existing windows
5575                // have been drawn.
5576                boolean haveBootMsg = false;
5577                boolean haveApp = false;
5578                // if the wallpaper service is disabled on the device, we're never going to have
5579                // wallpaper, don't bother waiting for it
5580                boolean haveWallpaper = false;
5581                boolean wallpaperEnabled = mContext.getResources().getBoolean(
5582                        com.android.internal.R.bool.config_enableWallpaperService)
5583                        && !mOnlyCore;
5584                boolean haveKeyguard = true;
5585                // TODO(multidisplay): Expand to all displays?
5586                final WindowList windows = getDefaultWindowListLocked();
5587                final int N = windows.size();
5588                for (int i=0; i<N; i++) {
5589                    WindowState w = windows.get(i);
5590                    if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
5591                        return;
5592                    }
5593                    if (w.isDrawnLw()) {
5594                        if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
5595                            haveBootMsg = true;
5596                        } else if (w.mAttrs.type == TYPE_APPLICATION) {
5597                            haveApp = true;
5598                        } else if (w.mAttrs.type == TYPE_WALLPAPER) {
5599                            haveWallpaper = true;
5600                        } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
5601                            haveKeyguard = mPolicy.isKeyguardDrawnLw();
5602                        }
5603                    }
5604                }
5605
5606                if (DEBUG_SCREEN_ON || DEBUG_BOOT) {
5607                    Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages
5608                            + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
5609                            + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
5610                            + " haveKeyguard=" + haveKeyguard);
5611                }
5612
5613                // If we are turning on the screen to show the boot message,
5614                // don't do it until the boot message is actually displayed.
5615                if (!mSystemBooted && !haveBootMsg) {
5616                    return;
5617                }
5618
5619                // If we are turning on the screen after the boot is completed
5620                // normally, don't do so until we have the application and
5621                // wallpaper.
5622                if (mSystemBooted && ((!haveApp && !haveKeyguard) ||
5623                        (wallpaperEnabled && !haveWallpaper))) {
5624                    return;
5625                }
5626            }
5627
5628            mDisplayEnabled = true;
5629            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
5630            if (false) {
5631                StringWriter sw = new StringWriter();
5632                PrintWriter pw = new FastPrintWriter(sw, false, 1024);
5633                this.dump(null, pw, null);
5634                pw.flush();
5635                Slog.i(TAG, sw.toString());
5636            }
5637            try {
5638                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
5639                if (surfaceFlinger != null) {
5640                    //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
5641                    Parcel data = Parcel.obtain();
5642                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
5643                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
5644                                            data, null, 0);
5645                    data.recycle();
5646                }
5647            } catch (RemoteException ex) {
5648                Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
5649            }
5650
5651            // Enable input dispatch.
5652            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
5653        }
5654
5655        mPolicy.enableScreenAfterBoot();
5656
5657        // Make sure the last requested orientation has been applied.
5658        updateRotationUnchecked(false, false);
5659    }
5660
5661    public void showBootMessage(final CharSequence msg, final boolean always) {
5662        boolean first = false;
5663        synchronized(mWindowMap) {
5664            if (DEBUG_BOOT) {
5665                RuntimeException here = new RuntimeException("here");
5666                here.fillInStackTrace();
5667                Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always
5668                        + " mAllowBootMessages=" + mAllowBootMessages
5669                        + " mShowingBootMessages=" + mShowingBootMessages
5670                        + " mSystemBooted=" + mSystemBooted, here);
5671            }
5672            if (!mAllowBootMessages) {
5673                return;
5674            }
5675            if (!mShowingBootMessages) {
5676                if (!always) {
5677                    return;
5678                }
5679                first = true;
5680            }
5681            if (mSystemBooted) {
5682                return;
5683            }
5684            mShowingBootMessages = true;
5685            mPolicy.showBootMessage(msg, always);
5686        }
5687        if (first) {
5688            performEnableScreen();
5689        }
5690    }
5691
5692    public void hideBootMessagesLocked() {
5693        if (DEBUG_BOOT) {
5694            RuntimeException here = new RuntimeException("here");
5695            here.fillInStackTrace();
5696            Slog.i(TAG, "hideBootMessagesLocked: mDisplayEnabled=" + mDisplayEnabled
5697                    + " mForceDisplayEnabled=" + mForceDisplayEnabled
5698                    + " mShowingBootMessages=" + mShowingBootMessages
5699                    + " mSystemBooted=" + mSystemBooted, here);
5700        }
5701        if (mShowingBootMessages) {
5702            mShowingBootMessages = false;
5703            mPolicy.hideBootMessages();
5704        }
5705    }
5706
5707    @Override
5708    public void setInTouchMode(boolean mode) {
5709        synchronized(mWindowMap) {
5710            mInTouchMode = mode;
5711        }
5712    }
5713
5714    public void showCircularDisplayMaskIfNeeded() {
5715        // we're fullscreen and not hosted in an ActivityView
5716        if (mContext.getResources().getBoolean(
5717                com.android.internal.R.bool.config_windowIsRound)
5718                && mContext.getResources().getBoolean(
5719                com.android.internal.R.bool.config_windowShowCircularMask)) {
5720            mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
5721        }
5722    }
5723
5724    public void showCircularMask() {
5725        synchronized(mWindowMap) {
5726
5727            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5728                    ">>> OPEN TRANSACTION showDisplayMask");
5729            SurfaceControl.openTransaction();
5730            try {
5731                // TODO(multi-display): support multiple displays
5732                if (mCircularDisplayMask == null) {
5733                    int screenOffset = (int) mContext.getResources().getDimensionPixelSize(
5734                            com.android.internal.R.dimen.circular_display_mask_offset);
5735
5736                    mCircularDisplayMask = new CircularDisplayMask(
5737                            getDefaultDisplayContentLocked().getDisplay(),
5738                            mFxSession,
5739                            mPolicy.windowTypeToLayerLw(
5740                                    WindowManager.LayoutParams.TYPE_POINTER)
5741                                    * TYPE_LAYER_MULTIPLIER + 10, screenOffset);
5742                }
5743                mCircularDisplayMask.setVisibility(true);
5744            } finally {
5745                SurfaceControl.closeTransaction();
5746                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5747                        "<<< CLOSE TRANSACTION showDisplayMask");
5748            }
5749        }
5750    }
5751
5752    // TODO: more accounting of which pid(s) turned it on, keep count,
5753    // only allow disables from pids which have count on, etc.
5754    @Override
5755    public void showStrictModeViolation(boolean on) {
5756        int pid = Binder.getCallingPid();
5757        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
5758    }
5759
5760    private void showStrictModeViolation(int arg, int pid) {
5761        final boolean on = arg != 0;
5762        synchronized(mWindowMap) {
5763            // Ignoring requests to enable the red border from clients
5764            // which aren't on screen.  (e.g. Broadcast Receivers in
5765            // the background..)
5766            if (on) {
5767                boolean isVisible = false;
5768                final int numDisplays = mDisplayContents.size();
5769                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
5770                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
5771                    final int numWindows = windows.size();
5772                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
5773                        final WindowState ws = windows.get(winNdx);
5774                        if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
5775                            isVisible = true;
5776                            break;
5777                        }
5778                    }
5779                }
5780                if (!isVisible) {
5781                    return;
5782                }
5783            }
5784
5785            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5786                    ">>> OPEN TRANSACTION showStrictModeViolation");
5787            SurfaceControl.openTransaction();
5788            try {
5789                // TODO(multi-display): support multiple displays
5790                if (mStrictModeFlash == null) {
5791                    mStrictModeFlash = new StrictModeFlash(
5792                            getDefaultDisplayContentLocked().getDisplay(), mFxSession);
5793                }
5794                mStrictModeFlash.setVisibility(on);
5795            } finally {
5796                SurfaceControl.closeTransaction();
5797                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
5798                        "<<< CLOSE TRANSACTION showStrictModeViolation");
5799            }
5800        }
5801    }
5802
5803    @Override
5804    public void setStrictModeVisualIndicatorPreference(String value) {
5805        SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
5806    }
5807
5808    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
5809        if (rot == Surface.ROTATION_90) {
5810            final int tmp = crop.top;
5811            crop.top = dw - crop.right;
5812            crop.right = crop.bottom;
5813            crop.bottom = dw - crop.left;
5814            crop.left = tmp;
5815        } else if (rot == Surface.ROTATION_180) {
5816            int tmp = crop.top;
5817            crop.top = dh - crop.bottom;
5818            crop.bottom = dh - tmp;
5819            tmp = crop.right;
5820            crop.right = dw - crop.left;
5821            crop.left = dw - tmp;
5822        } else if (rot == Surface.ROTATION_270) {
5823            final int tmp = crop.top;
5824            crop.top = crop.left;
5825            crop.left = dh - crop.bottom;
5826            crop.bottom = crop.right;
5827            crop.right = dh - tmp;
5828        }
5829    }
5830
5831    /**
5832     * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
5833     * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
5834     * of the target image.
5835     *
5836     * @param displayId the Display to take a screenshot of.
5837     * @param width the width of the target bitmap
5838     * @param height the height of the target bitmap
5839     * @param force565 if true the returned bitmap will be RGB_565, otherwise it
5840     *                 will be the same config as the surface
5841     */
5842    @Override
5843    public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
5844            int height, boolean force565) {
5845        if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5846                "screenshotApplications()")) {
5847            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
5848        }
5849
5850        final DisplayContent displayContent = getDisplayContentLocked(displayId);
5851        if (displayContent == null) {
5852            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5853                    + ": returning null. No Display for displayId=" + displayId);
5854            return null;
5855        }
5856        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
5857        int dw = displayInfo.logicalWidth;
5858        int dh = displayInfo.logicalHeight;
5859        if (dw == 0 || dh == 0) {
5860            if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5861                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
5862            return null;
5863        }
5864
5865        Bitmap rawss = null;
5866
5867        int maxLayer = 0;
5868        final Rect frame = new Rect();
5869        final Rect stackBounds = new Rect();
5870
5871        float scale = 0;
5872        int rot = Surface.ROTATION_0;
5873
5874        boolean screenshotReady;
5875        int minLayer;
5876        if (appToken == null) {
5877            screenshotReady = true;
5878            minLayer = 0;
5879        } else {
5880            screenshotReady = false;
5881            minLayer = Integer.MAX_VALUE;
5882        }
5883
5884        int retryCount = 0;
5885        WindowState appWin = null;
5886
5887        final boolean appIsImTarget = mInputMethodTarget != null
5888                && mInputMethodTarget.mAppToken != null
5889                && mInputMethodTarget.mAppToken.appToken != null
5890                && mInputMethodTarget.mAppToken.appToken.asBinder() == appToken;
5891
5892        final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
5893                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
5894
5895        while (true) {
5896            if (retryCount++ > 0) {
5897                try {
5898                    Thread.sleep(100);
5899                } catch (InterruptedException e) {
5900                }
5901            }
5902            synchronized(mWindowMap) {
5903                // Figure out the part of the screen that is actually the app.
5904                appWin = null;
5905                final WindowList windows = displayContent.getWindowList();
5906                for (int i = windows.size() - 1; i >= 0; i--) {
5907                    WindowState ws = windows.get(i);
5908                    if (!ws.mHasSurface) {
5909                        continue;
5910                    }
5911                    if (ws.mLayer >= aboveAppLayer) {
5912                        continue;
5913                    }
5914                    if (ws.mIsImWindow) {
5915                        if (!appIsImTarget) {
5916                            continue;
5917                        }
5918                    } else if (ws.mIsWallpaper) {
5919                        // Fall through.
5920                    } else if (appToken != null) {
5921                        if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
5922                            // This app window is of no interest if it is not associated with the
5923                            // screenshot app.
5924                            continue;
5925                        }
5926                        appWin = ws;
5927                    }
5928
5929                    // Include this window.
5930
5931                    final WindowStateAnimator winAnim = ws.mWinAnimator;
5932                    if (maxLayer < winAnim.mSurfaceLayer) {
5933                        maxLayer = winAnim.mSurfaceLayer;
5934                    }
5935                    if (minLayer > winAnim.mSurfaceLayer) {
5936                        minLayer = winAnim.mSurfaceLayer;
5937                    }
5938
5939                    // Don't include wallpaper in bounds calculation
5940                    if (!ws.mIsWallpaper) {
5941                        final Rect wf = ws.mFrame;
5942                        final Rect cr = ws.mContentInsets;
5943                        int left = wf.left + cr.left;
5944                        int top = wf.top + cr.top;
5945                        int right = wf.right - cr.right;
5946                        int bottom = wf.bottom - cr.bottom;
5947                        frame.union(left, top, right, bottom);
5948                        ws.getStackBounds(stackBounds);
5949                        frame.intersect(stackBounds);
5950                    }
5951
5952                    if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
5953                            ws.isDisplayedLw()) {
5954                        screenshotReady = true;
5955                    }
5956                }
5957
5958                if (appToken != null && appWin == null) {
5959                    // Can't find a window to snapshot.
5960                    if (DEBUG_SCREENSHOT) Slog.i(TAG,
5961                            "Screenshot: Couldn't find a surface matching " + appToken);
5962                    return null;
5963                }
5964
5965                if (!screenshotReady) {
5966                    if (retryCount > MAX_SCREENSHOT_RETRIES) {
5967                        Slog.i(TAG, "Screenshot max retries " + retryCount + " of " + appToken +
5968                                " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
5969                                appWin.mWinAnimator.mDrawState)));
5970                        return null;
5971                    }
5972
5973                    // Delay and hope that window gets drawn.
5974                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot: No image ready for " + appToken
5975                            + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
5976                    continue;
5977                }
5978
5979                // Screenshot is ready to be taken. Everything from here below will continue
5980                // through the bottom of the loop and return a value. We only stay in the loop
5981                // because we don't want to release the mWindowMap lock until the screenshot is
5982                // taken.
5983
5984                if (maxLayer == 0) {
5985                    if (DEBUG_SCREENSHOT) Slog.i(TAG, "Screenshot of " + appToken
5986                            + ": returning null maxLayer=" + maxLayer);
5987                    return null;
5988                }
5989
5990                // Constrain frame to the screen size.
5991                frame.intersect(0, 0, dw, dh);
5992
5993                // Tell surface flinger what part of the image to crop. Take the top
5994                // right part of the application, and crop the larger dimension to fit.
5995                Rect crop = new Rect(frame);
5996                if (width / (float) frame.width() < height / (float) frame.height()) {
5997                    int cropWidth = (int)((float)width / (float)height * frame.height());
5998                    crop.right = crop.left + cropWidth;
5999                } else {
6000                    int cropHeight = (int)((float)height / (float)width * frame.width());
6001                    crop.bottom = crop.top + cropHeight;
6002                }
6003
6004                // The screenshot API does not apply the current screen rotation.
6005                rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
6006                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
6007                    final int tmp = width;
6008                    width = height;
6009                    height = tmp;
6010                    rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
6011                }
6012
6013                // Surfaceflinger is not aware of orientation, so convert our logical
6014                // crop to surfaceflinger's portrait orientation.
6015                convertCropForSurfaceFlinger(crop, rot, dw, dh);
6016
6017                if (DEBUG_SCREENSHOT) {
6018                    Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
6019                            + maxLayer + " appToken=" + appToken);
6020                    for (int i = 0; i < windows.size(); i++) {
6021                        WindowState win = windows.get(i);
6022                        Slog.i(TAG, win + ": " + win.mLayer
6023                                + " animLayer=" + win.mWinAnimator.mAnimLayer
6024                                + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
6025                    }
6026                }
6027
6028                ScreenRotationAnimation screenRotationAnimation =
6029                        mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6030                final boolean inRotation = screenRotationAnimation != null &&
6031                        screenRotationAnimation.isAnimating();
6032                if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
6033                        "Taking screenshot while rotating");
6034
6035                rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
6036                        inRotation);
6037                if (rawss == null) {
6038                    Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
6039                            + ") to layer " + maxLayer);
6040                    return null;
6041                }
6042            }
6043
6044            break;
6045        }
6046
6047        Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
6048                Config.RGB_565 : rawss.getConfig());
6049        if (DEBUG_SCREENSHOT) {
6050            bm.eraseColor(0xFF000000);
6051        }
6052        Matrix matrix = new Matrix();
6053        ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
6054        Canvas canvas = new Canvas(bm);
6055        canvas.drawBitmap(rawss, matrix, null);
6056        canvas.setBitmap(null);
6057
6058        if (DEBUG_SCREENSHOT) {
6059            // TEST IF IT's ALL BLACK
6060            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
6061            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
6062            boolean allBlack = true;
6063            final int firstColor = buffer[0];
6064            for (int i = 0; i < buffer.length; i++) {
6065                if (buffer[i] != firstColor) {
6066                    allBlack = false;
6067                    break;
6068                }
6069            }
6070            if (allBlack) {
6071                Slog.i(TAG, "Screenshot " + appWin + " was monochrome(" +
6072                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
6073                        (appWin != null ? appWin.mWinAnimator.mSurfaceLayer : "null") +
6074                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
6075            }
6076        }
6077
6078        rawss.recycle();
6079
6080        return bm;
6081    }
6082
6083    /**
6084     * Freeze rotation changes.  (Enable "rotation lock".)
6085     * Persists across reboots.
6086     * @param rotation The desired rotation to freeze to, or -1 to use the
6087     * current rotation.
6088     */
6089    @Override
6090    public void freezeRotation(int rotation) {
6091        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6092                "freezeRotation()")) {
6093            throw new SecurityException("Requires SET_ORIENTATION permission");
6094        }
6095        if (rotation < -1 || rotation > Surface.ROTATION_270) {
6096            throw new IllegalArgumentException("Rotation argument must be -1 or a valid "
6097                    + "rotation constant.");
6098        }
6099
6100        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
6101
6102        long origId = Binder.clearCallingIdentity();
6103        try {
6104            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
6105                    rotation == -1 ? mRotation : rotation);
6106        } finally {
6107            Binder.restoreCallingIdentity(origId);
6108        }
6109
6110        updateRotationUnchecked(false, false);
6111    }
6112
6113    /**
6114     * Thaw rotation changes.  (Disable "rotation lock".)
6115     * Persists across reboots.
6116     */
6117    @Override
6118    public void thawRotation() {
6119        if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
6120                "thawRotation()")) {
6121            throw new SecurityException("Requires SET_ORIENTATION permission");
6122        }
6123
6124        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
6125
6126        long origId = Binder.clearCallingIdentity();
6127        try {
6128            mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE,
6129                    777); // rot not used
6130        } finally {
6131            Binder.restoreCallingIdentity(origId);
6132        }
6133
6134        updateRotationUnchecked(false, false);
6135    }
6136
6137    /**
6138     * Recalculate the current rotation.
6139     *
6140     * Called by the window manager policy whenever the state of the system changes
6141     * such that the current rotation might need to be updated, such as when the
6142     * device is docked or rotated into a new posture.
6143     */
6144    @Override
6145    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
6146        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
6147    }
6148
6149    /**
6150     * Temporarily pauses rotation changes until resumed.
6151     *
6152     * This can be used to prevent rotation changes from occurring while the user is
6153     * performing certain operations, such as drag and drop.
6154     *
6155     * This call nests and must be matched by an equal number of calls to
6156     * {@link #resumeRotationLocked}.
6157     */
6158    void pauseRotationLocked() {
6159        mDeferredRotationPauseCount += 1;
6160    }
6161
6162    /**
6163     * Resumes normal rotation changes after being paused.
6164     */
6165    void resumeRotationLocked() {
6166        if (mDeferredRotationPauseCount > 0) {
6167            mDeferredRotationPauseCount -= 1;
6168            if (mDeferredRotationPauseCount == 0) {
6169                boolean changed = updateRotationUncheckedLocked(false);
6170                if (changed) {
6171                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
6172                }
6173            }
6174        }
6175    }
6176
6177    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
6178        if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
6179                   + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
6180
6181        long origId = Binder.clearCallingIdentity();
6182        boolean changed;
6183        synchronized(mWindowMap) {
6184            changed = updateRotationUncheckedLocked(false);
6185            if (!changed || forceRelayout) {
6186                getDefaultDisplayContentLocked().layoutNeeded = true;
6187                performLayoutAndPlaceSurfacesLocked();
6188            }
6189        }
6190
6191        if (changed || alwaysSendConfiguration) {
6192            sendNewConfiguration();
6193        }
6194
6195        Binder.restoreCallingIdentity(origId);
6196    }
6197
6198    // TODO(multidisplay): Rotate any display?
6199    /**
6200     * Updates the current rotation.
6201     *
6202     * Returns true if the rotation has been changed.  In this case YOU
6203     * MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
6204     */
6205    public boolean updateRotationUncheckedLocked(boolean inTransaction) {
6206        if (mDeferredRotationPauseCount > 0) {
6207            // Rotation updates have been paused temporarily.  Defer the update until
6208            // updates have been resumed.
6209            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, rotation is paused.");
6210            return false;
6211        }
6212
6213        ScreenRotationAnimation screenRotationAnimation =
6214                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6215        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
6216            // Rotation updates cannot be performed while the previous rotation change
6217            // animation is still in progress.  Skip this update.  We will try updating
6218            // again after the animation is finished and the display is unfrozen.
6219            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, animation in progress.");
6220            return false;
6221        }
6222
6223        if (!mDisplayEnabled) {
6224            // No point choosing a rotation if the display is not enabled.
6225            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation, display is not enabled.");
6226            return false;
6227        }
6228
6229        // TODO: Implement forced rotation changes.
6230        //       Set mAltOrientation to indicate that the application is receiving
6231        //       an orientation that has different metrics than it expected.
6232        //       eg. Portrait instead of Landscape.
6233
6234        int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
6235        boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
6236                mForcedAppOrientation, rotation);
6237
6238        if (DEBUG_ORIENTATION) {
6239            Slog.v(TAG, "Application requested orientation "
6240                    + mForcedAppOrientation + ", got rotation " + rotation
6241                    + " which has " + (altOrientation ? "incompatible" : "compatible")
6242                    + " metrics");
6243        }
6244
6245        if (mRotation == rotation && mAltOrientation == altOrientation) {
6246            // No change.
6247            return false;
6248        }
6249
6250        if (DEBUG_ORIENTATION) {
6251            Slog.v(TAG,
6252                "Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
6253                + " from " + mRotation + (mAltOrientation ? " (alt)" : "")
6254                + ", forceApp=" + mForcedAppOrientation);
6255        }
6256
6257        mRotation = rotation;
6258        mAltOrientation = altOrientation;
6259        mPolicy.setRotationLw(mRotation);
6260
6261        mWindowsFreezingScreen = true;
6262        mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
6263        mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT, WINDOW_FREEZE_TIMEOUT_DURATION);
6264        mWaitingForConfig = true;
6265        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6266        displayContent.layoutNeeded = true;
6267        final int[] anim = new int[2];
6268        if (displayContent.isDimming()) {
6269            anim[0] = anim[1] = 0;
6270        } else {
6271            mPolicy.selectRotationAnimationLw(anim);
6272        }
6273        startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
6274        // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
6275        screenRotationAnimation =
6276                mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
6277
6278        // We need to update our screen size information to match the new
6279        // rotation.  Note that this is redundant with the later call to
6280        // sendNewConfiguration() that must be called after this function
6281        // returns...  however we need to do the screen size part of that
6282        // before then so we have the correct size to use when initializing
6283        // the rotation animation for the new rotation.
6284        computeScreenConfigurationLocked(null);
6285
6286        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6287        if (!inTransaction) {
6288            if (SHOW_TRANSACTIONS) {
6289                Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
6290            }
6291            SurfaceControl.openTransaction();
6292        }
6293        try {
6294            // NOTE: We disable the rotation in the emulator because
6295            //       it doesn't support hardware OpenGL emulation yet.
6296            if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
6297                    && screenRotationAnimation.hasScreenshot()) {
6298                if (screenRotationAnimation.setRotationInTransaction(
6299                        rotation, mFxSession,
6300                        MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(),
6301                        displayInfo.logicalWidth, displayInfo.logicalHeight)) {
6302                    scheduleAnimationLocked();
6303                }
6304            }
6305
6306            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
6307        } finally {
6308            if (!inTransaction) {
6309                SurfaceControl.closeTransaction();
6310                if (SHOW_LIGHT_TRANSACTIONS) {
6311                    Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
6312                }
6313            }
6314        }
6315
6316        final WindowList windows = displayContent.getWindowList();
6317        for (int i = windows.size() - 1; i >= 0; i--) {
6318            WindowState w = windows.get(i);
6319            if (w.mHasSurface) {
6320                if (DEBUG_ORIENTATION) Slog.v(TAG, "Set mOrientationChanging of " + w);
6321                w.mOrientationChanging = true;
6322                mInnerFields.mOrientationChangeComplete = false;
6323            }
6324            w.mLastFreezeDuration = 0;
6325        }
6326
6327        for (int i=mRotationWatchers.size()-1; i>=0; i--) {
6328            try {
6329                mRotationWatchers.get(i).watcher.onRotationChanged(rotation);
6330            } catch (RemoteException e) {
6331            }
6332        }
6333
6334        //TODO (multidisplay): Magnification is supported only for the default display.
6335        if (mAccessibilityController != null
6336                && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
6337            mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
6338        }
6339
6340        return true;
6341    }
6342
6343    @Override
6344    public int getRotation() {
6345        return mRotation;
6346    }
6347
6348    @Override
6349    public boolean isRotationFrozen() {
6350        return mPolicy.getUserRotationMode() == WindowManagerPolicy.USER_ROTATION_LOCKED;
6351    }
6352
6353    @Override
6354    public int watchRotation(IRotationWatcher watcher) {
6355        final IBinder watcherBinder = watcher.asBinder();
6356        IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
6357            @Override
6358            public void binderDied() {
6359                synchronized (mWindowMap) {
6360                    for (int i=0; i<mRotationWatchers.size(); i++) {
6361                        if (watcherBinder == mRotationWatchers.get(i).watcher.asBinder()) {
6362                            RotationWatcher removed = mRotationWatchers.remove(i);
6363                            IBinder binder = removed.watcher.asBinder();
6364                            if (binder != null) {
6365                                binder.unlinkToDeath(this, 0);
6366                            }
6367                            i--;
6368                        }
6369                    }
6370                }
6371            }
6372        };
6373
6374        synchronized (mWindowMap) {
6375            try {
6376                watcher.asBinder().linkToDeath(dr, 0);
6377                mRotationWatchers.add(new RotationWatcher(watcher, dr));
6378            } catch (RemoteException e) {
6379                // Client died, no cleanup needed.
6380            }
6381
6382            return mRotation;
6383        }
6384    }
6385
6386    @Override
6387    public void removeRotationWatcher(IRotationWatcher watcher) {
6388        final IBinder watcherBinder = watcher.asBinder();
6389        synchronized (mWindowMap) {
6390            for (int i=0; i<mRotationWatchers.size(); i++) {
6391                RotationWatcher rotationWatcher = mRotationWatchers.get(i);
6392                if (watcherBinder == rotationWatcher.watcher.asBinder()) {
6393                    RotationWatcher removed = mRotationWatchers.remove(i);
6394                    IBinder binder = removed.watcher.asBinder();
6395                    if (binder != null) {
6396                        binder.unlinkToDeath(removed.deathRecipient, 0);
6397                    }
6398                    i--;
6399                }
6400            }
6401        }
6402    }
6403
6404    /**
6405     * Apps that use the compact menu panel (as controlled by the panelMenuIsCompact
6406     * theme attribute) on devices that feature a physical options menu key attempt to position
6407     * their menu panel window along the edge of the screen nearest the physical menu key.
6408     * This lowers the travel distance between invoking the menu panel and selecting
6409     * a menu option.
6410     *
6411     * This method helps control where that menu is placed. Its current implementation makes
6412     * assumptions about the menu key and its relationship to the screen based on whether
6413     * the device's natural orientation is portrait (width < height) or landscape.
6414     *
6415     * The menu key is assumed to be located along the bottom edge of natural-portrait
6416     * devices and along the right edge of natural-landscape devices. If these assumptions
6417     * do not hold for the target device, this method should be changed to reflect that.
6418     *
6419     * @return A {@link Gravity} value for placing the options menu window
6420     */
6421    @Override
6422    public int getPreferredOptionsPanelGravity() {
6423        synchronized (mWindowMap) {
6424            final int rotation = getRotation();
6425
6426            // TODO(multidisplay): Assume that such devices physical keys are on the main screen.
6427            final DisplayContent displayContent = getDefaultDisplayContentLocked();
6428            if (displayContent.mInitialDisplayWidth < displayContent.mInitialDisplayHeight) {
6429                // On devices with a natural orientation of portrait
6430                switch (rotation) {
6431                    default:
6432                    case Surface.ROTATION_0:
6433                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6434                    case Surface.ROTATION_90:
6435                        return Gravity.RIGHT | Gravity.BOTTOM;
6436                    case Surface.ROTATION_180:
6437                        return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6438                    case Surface.ROTATION_270:
6439                        return Gravity.START | Gravity.BOTTOM;
6440                }
6441            }
6442
6443            // On devices with a natural orientation of landscape
6444            switch (rotation) {
6445                default:
6446                case Surface.ROTATION_0:
6447                    return Gravity.RIGHT | Gravity.BOTTOM;
6448                case Surface.ROTATION_90:
6449                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6450                case Surface.ROTATION_180:
6451                    return Gravity.START | Gravity.BOTTOM;
6452                case Surface.ROTATION_270:
6453                    return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
6454            }
6455        }
6456    }
6457
6458    /**
6459     * Starts the view server on the specified port.
6460     *
6461     * @param port The port to listener to.
6462     *
6463     * @return True if the server was successfully started, false otherwise.
6464     *
6465     * @see com.android.server.wm.ViewServer
6466     * @see com.android.server.wm.ViewServer#VIEW_SERVER_DEFAULT_PORT
6467     */
6468    @Override
6469    public boolean startViewServer(int port) {
6470        if (isSystemSecure()) {
6471            return false;
6472        }
6473
6474        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
6475            return false;
6476        }
6477
6478        if (port < 1024) {
6479            return false;
6480        }
6481
6482        if (mViewServer != null) {
6483            if (!mViewServer.isRunning()) {
6484                try {
6485                    return mViewServer.start();
6486                } catch (IOException e) {
6487                    Slog.w(TAG, "View server did not start");
6488                }
6489            }
6490            return false;
6491        }
6492
6493        try {
6494            mViewServer = new ViewServer(this, port);
6495            return mViewServer.start();
6496        } catch (IOException e) {
6497            Slog.w(TAG, "View server did not start");
6498        }
6499        return false;
6500    }
6501
6502    private boolean isSystemSecure() {
6503        return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
6504                "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6505    }
6506
6507    /**
6508     * Stops the view server if it exists.
6509     *
6510     * @return True if the server stopped, false if it wasn't started or
6511     *         couldn't be stopped.
6512     *
6513     * @see com.android.server.wm.ViewServer
6514     */
6515    @Override
6516    public boolean stopViewServer() {
6517        if (isSystemSecure()) {
6518            return false;
6519        }
6520
6521        if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
6522            return false;
6523        }
6524
6525        if (mViewServer != null) {
6526            return mViewServer.stop();
6527        }
6528        return false;
6529    }
6530
6531    /**
6532     * Indicates whether the view server is running.
6533     *
6534     * @return True if the server is running, false otherwise.
6535     *
6536     * @see com.android.server.wm.ViewServer
6537     */
6538    @Override
6539    public boolean isViewServerRunning() {
6540        if (isSystemSecure()) {
6541            return false;
6542        }
6543
6544        if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
6545            return false;
6546        }
6547
6548        return mViewServer != null && mViewServer.isRunning();
6549    }
6550
6551    /**
6552     * Lists all availble windows in the system. The listing is written in the
6553     * specified Socket's output stream with the following syntax:
6554     * windowHashCodeInHexadecimal windowName
6555     * Each line of the ouput represents a different window.
6556     *
6557     * @param client The remote client to send the listing to.
6558     * @return False if an error occured, true otherwise.
6559     */
6560    boolean viewServerListWindows(Socket client) {
6561        if (isSystemSecure()) {
6562            return false;
6563        }
6564
6565        boolean result = true;
6566
6567        WindowList windows = new WindowList();
6568        synchronized (mWindowMap) {
6569            //noinspection unchecked
6570            final int numDisplays = mDisplayContents.size();
6571            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6572                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
6573                windows.addAll(displayContent.getWindowList());
6574            }
6575        }
6576
6577        BufferedWriter out = null;
6578
6579        // Any uncaught exception will crash the system process
6580        try {
6581            OutputStream clientStream = client.getOutputStream();
6582            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6583
6584            final int count = windows.size();
6585            for (int i = 0; i < count; i++) {
6586                final WindowState w = windows.get(i);
6587                out.write(Integer.toHexString(System.identityHashCode(w)));
6588                out.write(' ');
6589                out.append(w.mAttrs.getTitle());
6590                out.write('\n');
6591            }
6592
6593            out.write("DONE.\n");
6594            out.flush();
6595        } catch (Exception e) {
6596            result = false;
6597        } finally {
6598            if (out != null) {
6599                try {
6600                    out.close();
6601                } catch (IOException e) {
6602                    result = false;
6603                }
6604            }
6605        }
6606
6607        return result;
6608    }
6609
6610    // TODO(multidisplay): Extend to multiple displays.
6611    /**
6612     * Returns the focused window in the following format:
6613     * windowHashCodeInHexadecimal windowName
6614     *
6615     * @param client The remote client to send the listing to.
6616     * @return False if an error occurred, true otherwise.
6617     */
6618    boolean viewServerGetFocusedWindow(Socket client) {
6619        if (isSystemSecure()) {
6620            return false;
6621        }
6622
6623        boolean result = true;
6624
6625        WindowState focusedWindow = getFocusedWindow();
6626
6627        BufferedWriter out = null;
6628
6629        // Any uncaught exception will crash the system process
6630        try {
6631            OutputStream clientStream = client.getOutputStream();
6632            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
6633
6634            if(focusedWindow != null) {
6635                out.write(Integer.toHexString(System.identityHashCode(focusedWindow)));
6636                out.write(' ');
6637                out.append(focusedWindow.mAttrs.getTitle());
6638            }
6639            out.write('\n');
6640            out.flush();
6641        } catch (Exception e) {
6642            result = false;
6643        } finally {
6644            if (out != null) {
6645                try {
6646                    out.close();
6647                } catch (IOException e) {
6648                    result = false;
6649                }
6650            }
6651        }
6652
6653        return result;
6654    }
6655
6656    /**
6657     * Sends a command to a target window. The result of the command, if any, will be
6658     * written in the output stream of the specified socket.
6659     *
6660     * The parameters must follow this syntax:
6661     * windowHashcode extra
6662     *
6663     * Where XX is the length in characeters of the windowTitle.
6664     *
6665     * The first parameter is the target window. The window with the specified hashcode
6666     * will be the target. If no target can be found, nothing happens. The extra parameters
6667     * will be delivered to the target window and as parameters to the command itself.
6668     *
6669     * @param client The remote client to sent the result, if any, to.
6670     * @param command The command to execute.
6671     * @param parameters The command parameters.
6672     *
6673     * @return True if the command was successfully delivered, false otherwise. This does
6674     *         not indicate whether the command itself was successful.
6675     */
6676    boolean viewServerWindowCommand(Socket client, String command, String parameters) {
6677        if (isSystemSecure()) {
6678            return false;
6679        }
6680
6681        boolean success = true;
6682        Parcel data = null;
6683        Parcel reply = null;
6684
6685        BufferedWriter out = null;
6686
6687        // Any uncaught exception will crash the system process
6688        try {
6689            // Find the hashcode of the window
6690            int index = parameters.indexOf(' ');
6691            if (index == -1) {
6692                index = parameters.length();
6693            }
6694            final String code = parameters.substring(0, index);
6695            int hashCode = (int) Long.parseLong(code, 16);
6696
6697            // Extract the command's parameter after the window description
6698            if (index < parameters.length()) {
6699                parameters = parameters.substring(index + 1);
6700            } else {
6701                parameters = "";
6702            }
6703
6704            final WindowState window = findWindow(hashCode);
6705            if (window == null) {
6706                return false;
6707            }
6708
6709            data = Parcel.obtain();
6710            data.writeInterfaceToken("android.view.IWindow");
6711            data.writeString(command);
6712            data.writeString(parameters);
6713            data.writeInt(1);
6714            ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
6715
6716            reply = Parcel.obtain();
6717
6718            final IBinder binder = window.mClient.asBinder();
6719            // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
6720            binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
6721
6722            reply.readException();
6723
6724            if (!client.isOutputShutdown()) {
6725                out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
6726                out.write("DONE\n");
6727                out.flush();
6728            }
6729
6730        } catch (Exception e) {
6731            Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
6732            success = false;
6733        } finally {
6734            if (data != null) {
6735                data.recycle();
6736            }
6737            if (reply != null) {
6738                reply.recycle();
6739            }
6740            if (out != null) {
6741                try {
6742                    out.close();
6743                } catch (IOException e) {
6744
6745                }
6746            }
6747        }
6748
6749        return success;
6750    }
6751
6752    public void addWindowChangeListener(WindowChangeListener listener) {
6753        synchronized(mWindowMap) {
6754            mWindowChangeListeners.add(listener);
6755        }
6756    }
6757
6758    public void removeWindowChangeListener(WindowChangeListener listener) {
6759        synchronized(mWindowMap) {
6760            mWindowChangeListeners.remove(listener);
6761        }
6762    }
6763
6764    private void notifyWindowsChanged() {
6765        WindowChangeListener[] windowChangeListeners;
6766        synchronized(mWindowMap) {
6767            if(mWindowChangeListeners.isEmpty()) {
6768                return;
6769            }
6770            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6771            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6772        }
6773        int N = windowChangeListeners.length;
6774        for(int i = 0; i < N; i++) {
6775            windowChangeListeners[i].windowsChanged();
6776        }
6777    }
6778
6779    private void notifyFocusChanged() {
6780        WindowChangeListener[] windowChangeListeners;
6781        synchronized(mWindowMap) {
6782            if(mWindowChangeListeners.isEmpty()) {
6783                return;
6784            }
6785            windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
6786            windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
6787        }
6788        int N = windowChangeListeners.length;
6789        for(int i = 0; i < N; i++) {
6790            windowChangeListeners[i].focusChanged();
6791        }
6792    }
6793
6794    private WindowState findWindow(int hashCode) {
6795        if (hashCode == -1) {
6796            // TODO(multidisplay): Extend to multiple displays.
6797            return getFocusedWindow();
6798        }
6799
6800        synchronized (mWindowMap) {
6801            final int numDisplays = mDisplayContents.size();
6802            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
6803                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
6804                final int numWindows = windows.size();
6805                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
6806                    final WindowState w = windows.get(winNdx);
6807                    if (System.identityHashCode(w) == hashCode) {
6808                        return w;
6809                    }
6810                }
6811            }
6812        }
6813
6814        return null;
6815    }
6816
6817    /*
6818     * Instruct the Activity Manager to fetch the current configuration and broadcast
6819     * that to config-changed listeners if appropriate.
6820     */
6821    void sendNewConfiguration() {
6822        try {
6823            mActivityManager.updateConfiguration(null);
6824        } catch (RemoteException e) {
6825        }
6826    }
6827
6828    public Configuration computeNewConfiguration() {
6829        synchronized (mWindowMap) {
6830            Configuration config = computeNewConfigurationLocked();
6831            if (config == null && mWaitingForConfig) {
6832                // Nothing changed but we are waiting for something... stop that!
6833                mWaitingForConfig = false;
6834                mLastFinishedFreezeSource = "new-config";
6835                performLayoutAndPlaceSurfacesLocked();
6836            }
6837            return config;
6838        }
6839    }
6840
6841    Configuration computeNewConfigurationLocked() {
6842        Configuration config = new Configuration();
6843        config.fontScale = 0;
6844        if (!computeScreenConfigurationLocked(config)) {
6845            return null;
6846        }
6847        return config;
6848    }
6849
6850    private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) {
6851        // TODO: Multidisplay: for now only use with default display.
6852        final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
6853        if (width < displayInfo.smallestNominalAppWidth) {
6854            displayInfo.smallestNominalAppWidth = width;
6855        }
6856        if (width > displayInfo.largestNominalAppWidth) {
6857            displayInfo.largestNominalAppWidth = width;
6858        }
6859        final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
6860        if (height < displayInfo.smallestNominalAppHeight) {
6861            displayInfo.smallestNominalAppHeight = height;
6862        }
6863        if (height > displayInfo.largestNominalAppHeight) {
6864            displayInfo.largestNominalAppHeight = height;
6865        }
6866    }
6867
6868    private int reduceConfigLayout(int curLayout, int rotation, float density,
6869            int dw, int dh) {
6870        // TODO: Multidisplay: for now only use with default display.
6871        // Get the app screen size at this rotation.
6872        int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6873        int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6874
6875        // Compute the screen layout size class for this rotation.
6876        int longSize = w;
6877        int shortSize = h;
6878        if (longSize < shortSize) {
6879            int tmp = longSize;
6880            longSize = shortSize;
6881            shortSize = tmp;
6882        }
6883        longSize = (int)(longSize/density);
6884        shortSize = (int)(shortSize/density);
6885        return Configuration.reduceScreenLayout(curLayout, longSize, shortSize);
6886    }
6887
6888    private void computeSizeRangesAndScreenLayout(DisplayInfo displayInfo, boolean rotated,
6889                  int dw, int dh, float density, Configuration outConfig) {
6890        // TODO: Multidisplay: for now only use with default display.
6891
6892        // We need to determine the smallest width that will occur under normal
6893        // operation.  To this, start with the base screen size and compute the
6894        // width under the different possible rotations.  We need to un-rotate
6895        // the current screen dimensions before doing this.
6896        int unrotDw, unrotDh;
6897        if (rotated) {
6898            unrotDw = dh;
6899            unrotDh = dw;
6900        } else {
6901            unrotDw = dw;
6902            unrotDh = dh;
6903        }
6904        displayInfo.smallestNominalAppWidth = 1<<30;
6905        displayInfo.smallestNominalAppHeight = 1<<30;
6906        displayInfo.largestNominalAppWidth = 0;
6907        displayInfo.largestNominalAppHeight = 0;
6908        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_0, unrotDw, unrotDh);
6909        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_90, unrotDh, unrotDw);
6910        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_180, unrotDw, unrotDh);
6911        adjustDisplaySizeRanges(displayInfo, Surface.ROTATION_270, unrotDh, unrotDw);
6912        int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
6913        sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
6914        sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
6915        sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
6916        sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
6917        outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
6918        outConfig.screenLayout = sl;
6919    }
6920
6921    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
6922            int dw, int dh) {
6923        // TODO: Multidisplay: for now only use with default display.
6924        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
6925        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
6926        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
6927        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
6928        if (curSize == 0 || size < curSize) {
6929            curSize = size;
6930        }
6931        return curSize;
6932    }
6933
6934    private int computeCompatSmallestWidth(boolean rotated, DisplayMetrics dm, int dw, int dh) {
6935        // TODO: Multidisplay: for now only use with default display.
6936        mTmpDisplayMetrics.setTo(dm);
6937        final DisplayMetrics tmpDm = mTmpDisplayMetrics;
6938        final int unrotDw, unrotDh;
6939        if (rotated) {
6940            unrotDw = dh;
6941            unrotDh = dw;
6942        } else {
6943            unrotDw = dw;
6944            unrotDh = dh;
6945        }
6946        int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, tmpDm, unrotDw, unrotDh);
6947        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, tmpDm, unrotDh, unrotDw);
6948        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, tmpDm, unrotDw, unrotDh);
6949        sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, tmpDm, unrotDh, unrotDw);
6950        return sw;
6951    }
6952
6953    boolean computeScreenConfigurationLocked(Configuration config) {
6954        if (!mDisplayReady) {
6955            return false;
6956        }
6957
6958        // TODO(multidisplay): For now, apply Configuration to main screen only.
6959        final DisplayContent displayContent = getDefaultDisplayContentLocked();
6960
6961        // Use the effective "visual" dimensions based on current rotation
6962        final boolean rotated = (mRotation == Surface.ROTATION_90
6963                || mRotation == Surface.ROTATION_270);
6964        final int realdw = rotated ?
6965                displayContent.mBaseDisplayHeight : displayContent.mBaseDisplayWidth;
6966        final int realdh = rotated ?
6967                displayContent.mBaseDisplayWidth : displayContent.mBaseDisplayHeight;
6968        int dw = realdw;
6969        int dh = realdh;
6970
6971        if (mAltOrientation) {
6972            if (realdw > realdh) {
6973                // Turn landscape into portrait.
6974                int maxw = (int)(realdh/1.3f);
6975                if (maxw < realdw) {
6976                    dw = maxw;
6977                }
6978            } else {
6979                // Turn portrait into landscape.
6980                int maxh = (int)(realdw/1.3f);
6981                if (maxh < realdh) {
6982                    dh = maxh;
6983                }
6984            }
6985        }
6986
6987        if (config != null) {
6988            config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
6989                    Configuration.ORIENTATION_LANDSCAPE;
6990        }
6991
6992        // Update application display metrics.
6993        final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
6994        final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
6995        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
6996        synchronized(displayContent.mDisplaySizeLock) {
6997            displayInfo.rotation = mRotation;
6998            displayInfo.logicalWidth = dw;
6999            displayInfo.logicalHeight = dh;
7000            displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
7001            displayInfo.appWidth = appWidth;
7002            displayInfo.appHeight = appHeight;
7003            displayInfo.getLogicalMetrics(mRealDisplayMetrics,
7004                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
7005            displayInfo.getAppMetrics(mDisplayMetrics);
7006            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
7007                    displayContent.getDisplayId(), displayInfo);
7008        }
7009        if (false) {
7010            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
7011        }
7012
7013        final DisplayMetrics dm = mDisplayMetrics;
7014        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
7015                mCompatDisplayMetrics);
7016
7017        if (config != null) {
7018            config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
7019                    / dm.density);
7020            config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
7021                    / dm.density);
7022            computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
7023
7024            config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
7025            config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
7026            config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
7027            config.densityDpi = displayContent.mBaseDisplayDensity;
7028
7029            // Update the configuration based on available input devices, lid switch,
7030            // and platform configuration.
7031            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7032            config.keyboard = Configuration.KEYBOARD_NOKEYS;
7033            config.navigation = Configuration.NAVIGATION_NONAV;
7034
7035            int keyboardPresence = 0;
7036            int navigationPresence = 0;
7037            final InputDevice[] devices = mInputManager.getInputDevices();
7038            final int len = devices.length;
7039            for (int i = 0; i < len; i++) {
7040                InputDevice device = devices[i];
7041                if (!device.isVirtual()) {
7042                    final int sources = device.getSources();
7043                    final int presenceFlag = device.isExternal() ?
7044                            WindowManagerPolicy.PRESENCE_EXTERNAL :
7045                                    WindowManagerPolicy.PRESENCE_INTERNAL;
7046
7047                    if (mIsTouchDevice) {
7048                        if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
7049                                InputDevice.SOURCE_TOUCHSCREEN) {
7050                            config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
7051                        }
7052                    } else {
7053                        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
7054                    }
7055
7056                    if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
7057                        config.navigation = Configuration.NAVIGATION_TRACKBALL;
7058                        navigationPresence |= presenceFlag;
7059                    } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
7060                            && config.navigation == Configuration.NAVIGATION_NONAV) {
7061                        config.navigation = Configuration.NAVIGATION_DPAD;
7062                        navigationPresence |= presenceFlag;
7063                    }
7064
7065                    if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
7066                        config.keyboard = Configuration.KEYBOARD_QWERTY;
7067                        keyboardPresence |= presenceFlag;
7068                    }
7069                }
7070            }
7071
7072            // Determine whether a hard keyboard is available and enabled.
7073            boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
7074            if (hardKeyboardAvailable != mHardKeyboardAvailable) {
7075                mHardKeyboardAvailable = hardKeyboardAvailable;
7076                mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7077                mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
7078            }
7079            if (mShowImeWithHardKeyboard) {
7080                config.keyboard = Configuration.KEYBOARD_NOKEYS;
7081            }
7082
7083            // Let the policy update hidden states.
7084            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
7085            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
7086            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
7087            mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
7088        }
7089
7090        return true;
7091    }
7092
7093    public boolean isHardKeyboardAvailable() {
7094        synchronized (mWindowMap) {
7095            return mHardKeyboardAvailable;
7096        }
7097    }
7098
7099    public void updateShowImeWithHardKeyboard() {
7100        boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
7101                mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
7102                mCurrentUserId) == 1;
7103        synchronized (mWindowMap) {
7104            mShowImeWithHardKeyboard = showImeWithHardKeyboard;
7105        }
7106    }
7107
7108    public void setOnHardKeyboardStatusChangeListener(
7109            OnHardKeyboardStatusChangeListener listener) {
7110        synchronized (mWindowMap) {
7111            mHardKeyboardStatusChangeListener = listener;
7112        }
7113    }
7114
7115    void notifyHardKeyboardStatusChange() {
7116        final boolean available;
7117        final OnHardKeyboardStatusChangeListener listener;
7118        synchronized (mWindowMap) {
7119            listener = mHardKeyboardStatusChangeListener;
7120            available = mHardKeyboardAvailable;
7121        }
7122        if (listener != null) {
7123            listener.onHardKeyboardStatusChange(available);
7124        }
7125    }
7126
7127    // -------------------------------------------------------------
7128    // Drag and drop
7129    // -------------------------------------------------------------
7130
7131    IBinder prepareDragSurface(IWindow window, SurfaceSession session,
7132            int flags, int width, int height, Surface outSurface) {
7133        if (DEBUG_DRAG) {
7134            Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
7135                    + " flags=" + Integer.toHexString(flags) + " win=" + window
7136                    + " asbinder=" + window.asBinder());
7137        }
7138
7139        final int callerPid = Binder.getCallingPid();
7140        final long origId = Binder.clearCallingIdentity();
7141        IBinder token = null;
7142
7143        try {
7144            synchronized (mWindowMap) {
7145                try {
7146                    if (mDragState == null) {
7147                        // TODO(multi-display): support other displays
7148                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
7149                        final Display display = displayContent.getDisplay();
7150                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
7151                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
7152                        surface.setLayerStack(display.getLayerStack());
7153                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
7154                                + surface + ": CREATE");
7155                        outSurface.copyFrom(surface);
7156                        final IBinder winBinder = window.asBinder();
7157                        token = new Binder();
7158                        mDragState = new DragState(this, token, surface, /*flags*/ 0, winBinder);
7159                        token = mDragState.mToken = new Binder();
7160
7161                        // 5 second timeout for this window to actually begin the drag
7162                        mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
7163                        Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
7164                        mH.sendMessageDelayed(msg, 5000);
7165                    } else {
7166                        Slog.w(TAG, "Drag already in progress");
7167                    }
7168                } catch (OutOfResourcesException e) {
7169                    Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
7170                    if (mDragState != null) {
7171                        mDragState.reset();
7172                        mDragState = null;
7173                    }
7174                }
7175            }
7176        } finally {
7177            Binder.restoreCallingIdentity(origId);
7178        }
7179
7180        return token;
7181    }
7182
7183    // -------------------------------------------------------------
7184    // Input Events and Focus Management
7185    // -------------------------------------------------------------
7186
7187    final InputMonitor mInputMonitor = new InputMonitor(this);
7188    private boolean mEventDispatchingEnabled;
7189
7190    @Override
7191    public void pauseKeyDispatching(IBinder _token) {
7192        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7193                "pauseKeyDispatching()")) {
7194            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7195        }
7196
7197        synchronized (mWindowMap) {
7198            WindowToken token = mTokenMap.get(_token);
7199            if (token != null) {
7200                mInputMonitor.pauseDispatchingLw(token);
7201            }
7202        }
7203    }
7204
7205    @Override
7206    public void resumeKeyDispatching(IBinder _token) {
7207        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7208                "resumeKeyDispatching()")) {
7209            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7210        }
7211
7212        synchronized (mWindowMap) {
7213            WindowToken token = mTokenMap.get(_token);
7214            if (token != null) {
7215                mInputMonitor.resumeDispatchingLw(token);
7216            }
7217        }
7218    }
7219
7220    @Override
7221    public void setEventDispatching(boolean enabled) {
7222        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
7223                "setEventDispatching()")) {
7224            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
7225        }
7226
7227        synchronized (mWindowMap) {
7228            mEventDispatchingEnabled = enabled;
7229            if (mDisplayEnabled) {
7230                mInputMonitor.setEventDispatchingLw(enabled);
7231            }
7232        }
7233    }
7234
7235    private WindowState getFocusedWindow() {
7236        synchronized (mWindowMap) {
7237            return getFocusedWindowLocked();
7238        }
7239    }
7240
7241    private WindowState getFocusedWindowLocked() {
7242        return mCurrentFocus;
7243    }
7244
7245    public boolean detectSafeMode() {
7246        if (!mInputMonitor.waitForInputDevicesReady(
7247                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
7248            Slog.w(TAG, "Devices still not ready after waiting "
7249                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
7250                   + " milliseconds before attempting to detect safe mode.");
7251        }
7252
7253        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7254                KeyEvent.KEYCODE_MENU);
7255        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
7256        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
7257                KeyEvent.KEYCODE_DPAD_CENTER);
7258        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
7259                InputManagerService.BTN_MOUSE);
7260        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
7261                KeyEvent.KEYCODE_VOLUME_DOWN);
7262        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
7263                || volumeDownState > 0;
7264        try {
7265            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
7266                mSafeMode = true;
7267                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
7268            }
7269        } catch (IllegalArgumentException e) {
7270        }
7271        if (mSafeMode) {
7272            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
7273                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
7274        } else {
7275            Log.i(TAG, "SAFE MODE not enabled");
7276        }
7277        mPolicy.setSafeMode(mSafeMode);
7278        return mSafeMode;
7279    }
7280
7281    public void displayReady() {
7282        displayReady(Display.DEFAULT_DISPLAY);
7283
7284        synchronized(mWindowMap) {
7285            final DisplayContent displayContent = getDefaultDisplayContentLocked();
7286            readForcedDisplaySizeAndDensityLocked(displayContent);
7287            mDisplayReady = true;
7288        }
7289
7290        try {
7291            mActivityManager.updateConfiguration(null);
7292        } catch (RemoteException e) {
7293        }
7294
7295        synchronized(mWindowMap) {
7296            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
7297                    PackageManager.FEATURE_TOUCHSCREEN);
7298            configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
7299        }
7300
7301        try {
7302            mActivityManager.updateConfiguration(null);
7303        } catch (RemoteException e) {
7304        }
7305    }
7306
7307    private void displayReady(int displayId) {
7308        synchronized(mWindowMap) {
7309            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7310            if (displayContent != null) {
7311                mAnimator.addDisplayLocked(displayId);
7312                synchronized(displayContent.mDisplaySizeLock) {
7313                    // Bootstrap the default logical display from the display manager.
7314                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
7315                    DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
7316                    if (newDisplayInfo != null) {
7317                        displayInfo.copyFrom(newDisplayInfo);
7318                    }
7319                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
7320                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
7321                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
7322                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
7323                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
7324                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
7325                    displayContent.mBaseDisplayRect.set(0, 0,
7326                            displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight);
7327                }
7328            }
7329        }
7330    }
7331
7332    public void systemReady() {
7333        mPolicy.systemReady();
7334    }
7335
7336    // -------------------------------------------------------------
7337    // Async Handler
7338    // -------------------------------------------------------------
7339
7340    final class H extends Handler {
7341        public static final int REPORT_FOCUS_CHANGE = 2;
7342        public static final int REPORT_LOSING_FOCUS = 3;
7343        public static final int DO_TRAVERSAL = 4;
7344        public static final int ADD_STARTING = 5;
7345        public static final int REMOVE_STARTING = 6;
7346        public static final int FINISHED_STARTING = 7;
7347        public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
7348        public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
7349        public static final int WINDOW_FREEZE_TIMEOUT = 11;
7350
7351        public static final int APP_TRANSITION_TIMEOUT = 13;
7352        public static final int PERSIST_ANIMATION_SCALE = 14;
7353        public static final int FORCE_GC = 15;
7354        public static final int ENABLE_SCREEN = 16;
7355        public static final int APP_FREEZE_TIMEOUT = 17;
7356        public static final int SEND_NEW_CONFIGURATION = 18;
7357        public static final int REPORT_WINDOWS_CHANGE = 19;
7358        public static final int DRAG_START_TIMEOUT = 20;
7359        public static final int DRAG_END_TIMEOUT = 21;
7360        public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
7361        public static final int BOOT_TIMEOUT = 23;
7362        public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
7363        public static final int SHOW_STRICT_MODE_VIOLATION = 25;
7364        public static final int DO_ANIMATION_CALLBACK = 26;
7365
7366        public static final int DO_DISPLAY_ADDED = 27;
7367        public static final int DO_DISPLAY_REMOVED = 28;
7368        public static final int DO_DISPLAY_CHANGED = 29;
7369
7370        public static final int CLIENT_FREEZE_TIMEOUT = 30;
7371        public static final int TAP_OUTSIDE_STACK = 31;
7372        public static final int NOTIFY_ACTIVITY_DRAWN = 32;
7373
7374        public static final int ALL_WINDOWS_DRAWN = 33;
7375
7376        public static final int NEW_ANIMATOR_SCALE = 34;
7377
7378        public static final int SHOW_DISPLAY_MASK = 35;
7379
7380        @Override
7381        public void handleMessage(Message msg) {
7382            if (DEBUG_WINDOW_TRACE) {
7383                Slog.v(TAG, "handleMessage: entry what=" + msg.what);
7384            }
7385            switch (msg.what) {
7386                case REPORT_FOCUS_CHANGE: {
7387                    WindowState lastFocus;
7388                    WindowState newFocus;
7389
7390                    synchronized(mWindowMap) {
7391                        lastFocus = mLastFocus;
7392                        newFocus = mCurrentFocus;
7393                        if (lastFocus == newFocus) {
7394                            // Focus is not changing, so nothing to do.
7395                            return;
7396                        }
7397                        mLastFocus = newFocus;
7398                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Focus moving from " + lastFocus +
7399                                " to " + newFocus);
7400                        if (newFocus != null && lastFocus != null
7401                                && !newFocus.isDisplayedLw()) {
7402                            //Slog.i(TAG, "Delaying loss of focus...");
7403                            mLosingFocus.add(lastFocus);
7404                            lastFocus = null;
7405                        }
7406                    }
7407
7408                    //System.out.println("Changing focus from " + lastFocus
7409                    //                   + " to " + newFocus);
7410                    if (newFocus != null) {
7411                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Gaining focus: " + newFocus);
7412                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
7413                        notifyFocusChanged();
7414                    }
7415
7416                    if (lastFocus != null) {
7417                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing focus: " + lastFocus);
7418                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
7419                    }
7420                } break;
7421
7422                case REPORT_LOSING_FOCUS: {
7423                    ArrayList<WindowState> losers;
7424
7425                    synchronized(mWindowMap) {
7426                        losers = mLosingFocus;
7427                        mLosingFocus = new ArrayList<WindowState>();
7428                    }
7429
7430                    final int N = losers.size();
7431                    for (int i=0; i<N; i++) {
7432                        if (DEBUG_FOCUS_LIGHT) Slog.i(TAG, "Losing delayed focus: " +
7433                                losers.get(i));
7434                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
7435                    }
7436                } break;
7437
7438                case DO_TRAVERSAL: {
7439                    synchronized(mWindowMap) {
7440                        mTraversalScheduled = false;
7441                        performLayoutAndPlaceSurfacesLocked();
7442                    }
7443                } break;
7444
7445                case ADD_STARTING: {
7446                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7447                    final StartingData sd = wtoken.startingData;
7448
7449                    if (sd == null) {
7450                        // Animation has been canceled... do nothing.
7451                        return;
7452                    }
7453
7454                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
7455                            + wtoken + ": pkg=" + sd.pkg);
7456
7457                    View view = null;
7458                    try {
7459                        view = mPolicy.addStartingWindow(
7460                            wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
7461                            sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
7462                    } catch (Exception e) {
7463                        Slog.w(TAG, "Exception when adding starting window", e);
7464                    }
7465
7466                    if (view != null) {
7467                        boolean abort = false;
7468
7469                        synchronized(mWindowMap) {
7470                            if (wtoken.removed || wtoken.startingData == null) {
7471                                // If the window was successfully added, then
7472                                // we need to remove it.
7473                                if (wtoken.startingWindow != null) {
7474                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7475                                            "Aborted starting " + wtoken
7476                                            + ": removed=" + wtoken.removed
7477                                            + " startingData=" + wtoken.startingData);
7478                                    wtoken.startingWindow = null;
7479                                    wtoken.startingData = null;
7480                                    abort = true;
7481                                }
7482                            } else {
7483                                wtoken.startingView = view;
7484                            }
7485                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
7486                                    "Added starting " + wtoken
7487                                    + ": startingWindow="
7488                                    + wtoken.startingWindow + " startingView="
7489                                    + wtoken.startingView);
7490                        }
7491
7492                        if (abort) {
7493                            try {
7494                                mPolicy.removeStartingWindow(wtoken.token, view);
7495                            } catch (Exception e) {
7496                                Slog.w(TAG, "Exception when removing starting window", e);
7497                            }
7498                        }
7499                    }
7500                } break;
7501
7502                case REMOVE_STARTING: {
7503                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7504                    IBinder token = null;
7505                    View view = null;
7506                    synchronized (mWindowMap) {
7507                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
7508                                + wtoken + ": startingWindow="
7509                                + wtoken.startingWindow + " startingView="
7510                                + wtoken.startingView);
7511                        if (wtoken.startingWindow != null) {
7512                            view = wtoken.startingView;
7513                            token = wtoken.token;
7514                            wtoken.startingData = null;
7515                            wtoken.startingView = null;
7516                            wtoken.startingWindow = null;
7517                            wtoken.startingDisplayed = false;
7518                        }
7519                    }
7520                    if (view != null) {
7521                        try {
7522                            mPolicy.removeStartingWindow(token, view);
7523                        } catch (Exception e) {
7524                            Slog.w(TAG, "Exception when removing starting window", e);
7525                        }
7526                    }
7527                } break;
7528
7529                case FINISHED_STARTING: {
7530                    IBinder token = null;
7531                    View view = null;
7532                    while (true) {
7533                        synchronized (mWindowMap) {
7534                            final int N = mFinishedStarting.size();
7535                            if (N <= 0) {
7536                                break;
7537                            }
7538                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
7539
7540                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
7541                                    "Finished starting " + wtoken
7542                                    + ": startingWindow=" + wtoken.startingWindow
7543                                    + " startingView=" + wtoken.startingView);
7544
7545                            if (wtoken.startingWindow == null) {
7546                                continue;
7547                            }
7548
7549                            view = wtoken.startingView;
7550                            token = wtoken.token;
7551                            wtoken.startingData = null;
7552                            wtoken.startingView = null;
7553                            wtoken.startingWindow = null;
7554                            wtoken.startingDisplayed = false;
7555                        }
7556
7557                        try {
7558                            mPolicy.removeStartingWindow(token, view);
7559                        } catch (Exception e) {
7560                            Slog.w(TAG, "Exception when removing starting window", e);
7561                        }
7562                    }
7563                } break;
7564
7565                case REPORT_APPLICATION_TOKEN_DRAWN: {
7566                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7567
7568                    try {
7569                        if (DEBUG_VISIBILITY) Slog.v(
7570                                TAG, "Reporting drawn in " + wtoken);
7571                        wtoken.appToken.windowsDrawn();
7572                    } catch (RemoteException ex) {
7573                    }
7574                } break;
7575
7576                case REPORT_APPLICATION_TOKEN_WINDOWS: {
7577                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
7578
7579                    boolean nowVisible = msg.arg1 != 0;
7580                    boolean nowGone = msg.arg2 != 0;
7581
7582                    try {
7583                        if (DEBUG_VISIBILITY) Slog.v(
7584                                TAG, "Reporting visible in " + wtoken
7585                                + " visible=" + nowVisible
7586                                + " gone=" + nowGone);
7587                        if (nowVisible) {
7588                            wtoken.appToken.windowsVisible();
7589                        } else {
7590                            wtoken.appToken.windowsGone();
7591                        }
7592                    } catch (RemoteException ex) {
7593                    }
7594                } break;
7595
7596                case WINDOW_FREEZE_TIMEOUT: {
7597                    // TODO(multidisplay): Can non-default displays rotate?
7598                    synchronized (mWindowMap) {
7599                        Slog.w(TAG, "Window freeze timeout expired.");
7600                        final WindowList windows = getDefaultWindowListLocked();
7601                        int i = windows.size();
7602                        while (i > 0) {
7603                            i--;
7604                            WindowState w = windows.get(i);
7605                            if (w.mOrientationChanging) {
7606                                w.mOrientationChanging = false;
7607                                w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
7608                                        - mDisplayFreezeTime);
7609                                Slog.w(TAG, "Force clearing orientation change: " + w);
7610                            }
7611                        }
7612                        performLayoutAndPlaceSurfacesLocked();
7613                    }
7614                    break;
7615                }
7616
7617                case APP_TRANSITION_TIMEOUT: {
7618                    synchronized (mWindowMap) {
7619                        if (mAppTransition.isTransitionSet()) {
7620                            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
7621                            mAppTransition.setTimeout();
7622                            performLayoutAndPlaceSurfacesLocked();
7623                        }
7624                    }
7625                    break;
7626                }
7627
7628                case PERSIST_ANIMATION_SCALE: {
7629                    Settings.Global.putFloat(mContext.getContentResolver(),
7630                            Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
7631                    Settings.Global.putFloat(mContext.getContentResolver(),
7632                            Settings.Global.TRANSITION_ANIMATION_SCALE,
7633                            mTransitionAnimationScaleSetting);
7634                    Settings.Global.putFloat(mContext.getContentResolver(),
7635                            Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting);
7636                    break;
7637                }
7638
7639                case FORCE_GC: {
7640                    synchronized (mWindowMap) {
7641                        // Since we're holding both mWindowMap and mAnimator we don't need to
7642                        // hold mAnimator.mLayoutToAnim.
7643                        if (mAnimator.mAnimating || mAnimationScheduled) {
7644                            // If we are animating, don't do the gc now but
7645                            // delay a bit so we don't interrupt the animation.
7646                            sendEmptyMessageDelayed(H.FORCE_GC, 2000);
7647                            return;
7648                        }
7649                        // If we are currently rotating the display, it will
7650                        // schedule a new message when done.
7651                        if (mDisplayFrozen) {
7652                            return;
7653                        }
7654                    }
7655                    Runtime.getRuntime().gc();
7656                    break;
7657                }
7658
7659                case ENABLE_SCREEN: {
7660                    performEnableScreen();
7661                    break;
7662                }
7663
7664                case APP_FREEZE_TIMEOUT: {
7665                    synchronized (mWindowMap) {
7666                        Slog.w(TAG, "App freeze timeout expired.");
7667                        final int numStacks = mStackIdToStack.size();
7668                        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
7669                            final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
7670                            final ArrayList<Task> tasks = stack.getTasks();
7671                            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
7672                                AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
7673                                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
7674                                    AppWindowToken tok = tokens.get(tokenNdx);
7675                                    if (tok.mAppAnimator.freezingScreen) {
7676                                        Slog.w(TAG, "Force clearing freeze: " + tok);
7677                                        unsetAppFreezingScreenLocked(tok, true, true);
7678                                    }
7679                                }
7680                            }
7681                        }
7682                    }
7683                    break;
7684                }
7685
7686                case CLIENT_FREEZE_TIMEOUT: {
7687                    synchronized (mWindowMap) {
7688                        if (mClientFreezingScreen) {
7689                            mClientFreezingScreen = false;
7690                            mLastFinishedFreezeSource = "client-timeout";
7691                            stopFreezingDisplayLocked();
7692                        }
7693                    }
7694                    break;
7695                }
7696
7697                case SEND_NEW_CONFIGURATION: {
7698                    removeMessages(SEND_NEW_CONFIGURATION);
7699                    sendNewConfiguration();
7700                    break;
7701                }
7702
7703                case REPORT_WINDOWS_CHANGE: {
7704                    if (mWindowsChanged) {
7705                        synchronized (mWindowMap) {
7706                            mWindowsChanged = false;
7707                        }
7708                        notifyWindowsChanged();
7709                    }
7710                    break;
7711                }
7712
7713                case DRAG_START_TIMEOUT: {
7714                    IBinder win = (IBinder)msg.obj;
7715                    if (DEBUG_DRAG) {
7716                        Slog.w(TAG, "Timeout starting drag by win " + win);
7717                    }
7718                    synchronized (mWindowMap) {
7719                        // !!! TODO: ANR the app that has failed to start the drag in time
7720                        if (mDragState != null) {
7721                            mDragState.unregister();
7722                            mInputMonitor.updateInputWindowsLw(true /*force*/);
7723                            mDragState.reset();
7724                            mDragState = null;
7725                        }
7726                    }
7727                    break;
7728                }
7729
7730                case DRAG_END_TIMEOUT: {
7731                    IBinder win = (IBinder)msg.obj;
7732                    if (DEBUG_DRAG) {
7733                        Slog.w(TAG, "Timeout ending drag to win " + win);
7734                    }
7735                    synchronized (mWindowMap) {
7736                        // !!! TODO: ANR the drag-receiving app
7737                        if (mDragState != null) {
7738                            mDragState.mDragResult = false;
7739                            mDragState.endDragLw();
7740                        }
7741                    }
7742                    break;
7743                }
7744
7745                case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
7746                    notifyHardKeyboardStatusChange();
7747                    break;
7748                }
7749
7750                case BOOT_TIMEOUT: {
7751                    performBootTimeout();
7752                    break;
7753                }
7754
7755                case WAITING_FOR_DRAWN_TIMEOUT: {
7756                    Runnable callback = null;
7757                    synchronized (mWindowMap) {
7758                        Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
7759                        mWaitingForDrawn.clear();
7760                        callback = mWaitingForDrawnCallback;
7761                        mWaitingForDrawnCallback = null;
7762                    }
7763                    if (callback != null) {
7764                        callback.run();
7765                    }
7766                    break;
7767                }
7768
7769                case SHOW_STRICT_MODE_VIOLATION: {
7770                    showStrictModeViolation(msg.arg1, msg.arg2);
7771                    break;
7772                }
7773
7774                case SHOW_DISPLAY_MASK: {
7775                    showCircularMask();
7776                    break;
7777                }
7778
7779                case DO_ANIMATION_CALLBACK: {
7780                    try {
7781                        ((IRemoteCallback)msg.obj).sendResult(null);
7782                    } catch (RemoteException e) {
7783                    }
7784                    break;
7785                }
7786
7787                case DO_DISPLAY_ADDED:
7788                    handleDisplayAdded(msg.arg1);
7789                    break;
7790
7791                case DO_DISPLAY_REMOVED:
7792                    synchronized (mWindowMap) {
7793                        handleDisplayRemovedLocked(msg.arg1);
7794                    }
7795                    break;
7796
7797                case DO_DISPLAY_CHANGED:
7798                    synchronized (mWindowMap) {
7799                        handleDisplayChangedLocked(msg.arg1);
7800                    }
7801                    break;
7802
7803                case TAP_OUTSIDE_STACK: {
7804                    int stackId;
7805                    synchronized (mWindowMap) {
7806                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
7807                    }
7808                    if (stackId >= 0) {
7809                        try {
7810                            mActivityManager.setFocusedStack(stackId);
7811                        } catch (RemoteException e) {
7812                        }
7813                    }
7814                }
7815                break;
7816                case NOTIFY_ACTIVITY_DRAWN:
7817                    try {
7818                        mActivityManager.notifyActivityDrawn((IBinder) msg.obj);
7819                    } catch (RemoteException e) {
7820                    }
7821                    break;
7822                case ALL_WINDOWS_DRAWN: {
7823                    Runnable callback;
7824                    synchronized (mWindowMap) {
7825                        callback = mWaitingForDrawnCallback;
7826                        mWaitingForDrawnCallback = null;
7827                    }
7828                    if (callback != null) {
7829                        callback.run();
7830                    }
7831                }
7832                case NEW_ANIMATOR_SCALE: {
7833                    float scale = getCurrentAnimatorScale();
7834                    ValueAnimator.setDurationScale(scale);
7835                    Session session = (Session)msg.obj;
7836                    if (session != null) {
7837                        try {
7838                            session.mCallback.onAnimatorScaleChanged(scale);
7839                        } catch (RemoteException e) {
7840                        }
7841                    } else {
7842                        ArrayList<IWindowSessionCallback> callbacks
7843                                = new ArrayList<IWindowSessionCallback>();
7844                        synchronized (mWindowMap) {
7845                            for (int i=0; i<mSessions.size(); i++) {
7846                                callbacks.add(mSessions.valueAt(i).mCallback);
7847                            }
7848
7849                        }
7850                        for (int i=0; i<callbacks.size(); i++) {
7851                            try {
7852                                callbacks.get(i).onAnimatorScaleChanged(scale);
7853                            } catch (RemoteException e) {
7854                            }
7855                        }
7856                    }
7857                }
7858                break;
7859            }
7860            if (DEBUG_WINDOW_TRACE) {
7861                Slog.v(TAG, "handleMessage: exit");
7862            }
7863        }
7864    }
7865
7866    // -------------------------------------------------------------
7867    // IWindowManager API
7868    // -------------------------------------------------------------
7869
7870    @Override
7871    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
7872            IInputContext inputContext) {
7873        if (client == null) throw new IllegalArgumentException("null client");
7874        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
7875        Session session = new Session(this, callback, client, inputContext);
7876        return session;
7877    }
7878
7879    @Override
7880    public boolean inputMethodClientHasFocus(IInputMethodClient client) {
7881        synchronized (mWindowMap) {
7882            // The focus for the client is the window immediately below
7883            // where we would place the input method window.
7884            int idx = findDesiredInputMethodWindowIndexLocked(false);
7885            if (idx > 0) {
7886                // TODO(multidisplay): IMEs are only supported on the default display.
7887                WindowState imFocus = getDefaultWindowListLocked().get(idx-1);
7888                if (DEBUG_INPUT_METHOD) {
7889                    Slog.i(TAG, "Desired input method target: " + imFocus);
7890                    Slog.i(TAG, "Current focus: " + mCurrentFocus);
7891                    Slog.i(TAG, "Last focus: " + mLastFocus);
7892                }
7893                if (imFocus != null) {
7894                    // This may be a starting window, in which case we still want
7895                    // to count it as okay.
7896                    if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING
7897                            && imFocus.mAppToken != null) {
7898                        // The client has definitely started, so it really should
7899                        // have a window in this app token.  Let's look for it.
7900                        for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
7901                            WindowState w = imFocus.mAppToken.windows.get(i);
7902                            if (w != imFocus) {
7903                                Log.i(TAG, "Switching to real app window: " + w);
7904                                imFocus = w;
7905                                break;
7906                            }
7907                        }
7908                    }
7909                    if (DEBUG_INPUT_METHOD) {
7910                        Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7911                        if (imFocus.mSession.mClient != null) {
7912                            Slog.i(TAG, "IM target client binder: "
7913                                    + imFocus.mSession.mClient.asBinder());
7914                            Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7915                        }
7916                    }
7917                    if (imFocus.mSession.mClient != null &&
7918                            imFocus.mSession.mClient.asBinder() == client.asBinder()) {
7919                        return true;
7920                    }
7921                }
7922            }
7923
7924            // Okay, how about this...  what is the current focus?
7925            // It seems in some cases we may not have moved the IM
7926            // target window, such as when it was in a pop-up window,
7927            // so let's also look at the current focus.  (An example:
7928            // go to Gmail, start searching so the keyboard goes up,
7929            // press home.  Sometimes the IME won't go down.)
7930            // Would be nice to fix this more correctly, but it's
7931            // way at the end of a release, and this should be good enough.
7932            if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null
7933                    && mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) {
7934                return true;
7935            }
7936        }
7937        return false;
7938    }
7939
7940    @Override
7941    public void getInitialDisplaySize(int displayId, Point size) {
7942        synchronized (mWindowMap) {
7943            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7944            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7945                synchronized(displayContent.mDisplaySizeLock) {
7946                    size.x = displayContent.mInitialDisplayWidth;
7947                    size.y = displayContent.mInitialDisplayHeight;
7948                }
7949            }
7950        }
7951    }
7952
7953    @Override
7954    public void getBaseDisplaySize(int displayId, Point size) {
7955        synchronized (mWindowMap) {
7956            final DisplayContent displayContent = getDisplayContentLocked(displayId);
7957            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
7958                synchronized(displayContent.mDisplaySizeLock) {
7959                    size.x = displayContent.mBaseDisplayWidth;
7960                    size.y = displayContent.mBaseDisplayHeight;
7961                }
7962            }
7963        }
7964    }
7965
7966    @Override
7967    public void setForcedDisplaySize(int displayId, int width, int height) {
7968        if (mContext.checkCallingOrSelfPermission(
7969                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
7970                PackageManager.PERMISSION_GRANTED) {
7971            throw new SecurityException("Must hold permission " +
7972                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
7973        }
7974        if (displayId != Display.DEFAULT_DISPLAY) {
7975            throw new IllegalArgumentException("Can only set the default display");
7976        }
7977        final long ident = Binder.clearCallingIdentity();
7978        try {
7979            synchronized(mWindowMap) {
7980                // Set some sort of reasonable bounds on the size of the display that we
7981                // will try to emulate.
7982                final int MIN_WIDTH = 200;
7983                final int MIN_HEIGHT = 200;
7984                final int MAX_SCALE = 2;
7985                final DisplayContent displayContent = getDisplayContentLocked(displayId);
7986                if (displayContent != null) {
7987                    width = Math.min(Math.max(width, MIN_WIDTH),
7988                            displayContent.mInitialDisplayWidth * MAX_SCALE);
7989                    height = Math.min(Math.max(height, MIN_HEIGHT),
7990                            displayContent.mInitialDisplayHeight * MAX_SCALE);
7991                    setForcedDisplaySizeLocked(displayContent, width, height);
7992                    Settings.Global.putString(mContext.getContentResolver(),
7993                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
7994                }
7995            }
7996        } finally {
7997            Binder.restoreCallingIdentity(ident);
7998        }
7999    }
8000
8001    private void readForcedDisplaySizeAndDensityLocked(final DisplayContent displayContent) {
8002        String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
8003                Settings.Global.DISPLAY_SIZE_FORCED);
8004        if (sizeStr == null || sizeStr.length() == 0) {
8005            sizeStr = SystemProperties.get(SIZE_OVERRIDE, null);
8006        }
8007        if (sizeStr != null && sizeStr.length() > 0) {
8008            final int pos = sizeStr.indexOf(',');
8009            if (pos > 0 && sizeStr.lastIndexOf(',') == pos) {
8010                int width, height;
8011                try {
8012                    width = Integer.parseInt(sizeStr.substring(0, pos));
8013                    height = Integer.parseInt(sizeStr.substring(pos+1));
8014                    synchronized(displayContent.mDisplaySizeLock) {
8015                        if (displayContent.mBaseDisplayWidth != width
8016                                || displayContent.mBaseDisplayHeight != height) {
8017                            Slog.i(TAG, "FORCED DISPLAY SIZE: " + width + "x" + height);
8018                            displayContent.mBaseDisplayWidth = width;
8019                            displayContent.mBaseDisplayHeight = height;
8020                        }
8021                    }
8022                } catch (NumberFormatException ex) {
8023                }
8024            }
8025        }
8026        String densityStr = Settings.Global.getString(mContext.getContentResolver(),
8027                Settings.Global.DISPLAY_DENSITY_FORCED);
8028        if (densityStr == null || densityStr.length() == 0) {
8029            densityStr = SystemProperties.get(DENSITY_OVERRIDE, null);
8030        }
8031        if (densityStr != null && densityStr.length() > 0) {
8032            int density;
8033            try {
8034                density = Integer.parseInt(densityStr);
8035                synchronized(displayContent.mDisplaySizeLock) {
8036                    if (displayContent.mBaseDisplayDensity != density) {
8037                        Slog.i(TAG, "FORCED DISPLAY DENSITY: " + density);
8038                        displayContent.mBaseDisplayDensity = density;
8039                    }
8040                }
8041            } catch (NumberFormatException ex) {
8042            }
8043        }
8044    }
8045
8046    // displayContent must not be null
8047    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
8048        Slog.i(TAG, "Using new display size: " + width + "x" + height);
8049
8050        synchronized(displayContent.mDisplaySizeLock) {
8051            displayContent.mBaseDisplayWidth = width;
8052            displayContent.mBaseDisplayHeight = height;
8053        }
8054        reconfigureDisplayLocked(displayContent);
8055    }
8056
8057    @Override
8058    public void clearForcedDisplaySize(int displayId) {
8059        if (mContext.checkCallingOrSelfPermission(
8060                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8061                PackageManager.PERMISSION_GRANTED) {
8062            throw new SecurityException("Must hold permission " +
8063                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8064        }
8065        if (displayId != Display.DEFAULT_DISPLAY) {
8066            throw new IllegalArgumentException("Can only set the default display");
8067        }
8068        final long ident = Binder.clearCallingIdentity();
8069        try {
8070            synchronized(mWindowMap) {
8071                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8072                if (displayContent != null) {
8073                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
8074                            displayContent.mInitialDisplayHeight);
8075                    Settings.Global.putString(mContext.getContentResolver(),
8076                            Settings.Global.DISPLAY_SIZE_FORCED, "");
8077                }
8078            }
8079        } finally {
8080            Binder.restoreCallingIdentity(ident);
8081        }
8082    }
8083
8084    @Override
8085    public int getInitialDisplayDensity(int displayId) {
8086        synchronized (mWindowMap) {
8087            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8088            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8089                synchronized(displayContent.mDisplaySizeLock) {
8090                    return displayContent.mInitialDisplayDensity;
8091                }
8092            }
8093        }
8094        return -1;
8095    }
8096
8097    @Override
8098    public int getBaseDisplayDensity(int displayId) {
8099        synchronized (mWindowMap) {
8100            final DisplayContent displayContent = getDisplayContentLocked(displayId);
8101            if (displayContent != null && displayContent.hasAccess(Binder.getCallingUid())) {
8102                synchronized(displayContent.mDisplaySizeLock) {
8103                    return displayContent.mBaseDisplayDensity;
8104                }
8105            }
8106        }
8107        return -1;
8108    }
8109
8110    @Override
8111    public void setForcedDisplayDensity(int displayId, int density) {
8112        if (mContext.checkCallingOrSelfPermission(
8113                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8114                PackageManager.PERMISSION_GRANTED) {
8115            throw new SecurityException("Must hold permission " +
8116                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8117        }
8118        if (displayId != Display.DEFAULT_DISPLAY) {
8119            throw new IllegalArgumentException("Can only set the default display");
8120        }
8121        final long ident = Binder.clearCallingIdentity();
8122        try {
8123            synchronized(mWindowMap) {
8124                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8125                if (displayContent != null) {
8126                    setForcedDisplayDensityLocked(displayContent, density);
8127                    Settings.Global.putString(mContext.getContentResolver(),
8128                            Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
8129                }
8130            }
8131        } finally {
8132            Binder.restoreCallingIdentity(ident);
8133        }
8134    }
8135
8136    // displayContent must not be null
8137    private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
8138        Slog.i(TAG, "Using new display density: " + density);
8139
8140        synchronized(displayContent.mDisplaySizeLock) {
8141            displayContent.mBaseDisplayDensity = density;
8142        }
8143        reconfigureDisplayLocked(displayContent);
8144    }
8145
8146    @Override
8147    public void clearForcedDisplayDensity(int displayId) {
8148        if (mContext.checkCallingOrSelfPermission(
8149                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8150                PackageManager.PERMISSION_GRANTED) {
8151            throw new SecurityException("Must hold permission " +
8152                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8153        }
8154        if (displayId != Display.DEFAULT_DISPLAY) {
8155            throw new IllegalArgumentException("Can only set the default display");
8156        }
8157        final long ident = Binder.clearCallingIdentity();
8158        try {
8159            synchronized(mWindowMap) {
8160                final DisplayContent displayContent = getDisplayContentLocked(displayId);
8161                if (displayContent != null) {
8162                    setForcedDisplayDensityLocked(displayContent,
8163                            displayContent.mInitialDisplayDensity);
8164                    Settings.Global.putString(mContext.getContentResolver(),
8165                            Settings.Global.DISPLAY_DENSITY_FORCED, "");
8166                }
8167            }
8168        } finally {
8169            Binder.restoreCallingIdentity(ident);
8170        }
8171    }
8172
8173    // displayContent must not be null
8174    private void reconfigureDisplayLocked(DisplayContent displayContent) {
8175        // TODO: Multidisplay: for now only use with default display.
8176        configureDisplayPolicyLocked(displayContent);
8177        displayContent.layoutNeeded = true;
8178
8179        boolean configChanged = updateOrientationFromAppTokensLocked(false);
8180        mTempConfiguration.setToDefaults();
8181        mTempConfiguration.fontScale = mCurConfiguration.fontScale;
8182        if (computeScreenConfigurationLocked(mTempConfiguration)) {
8183            if (mCurConfiguration.diff(mTempConfiguration) != 0) {
8184                configChanged = true;
8185            }
8186        }
8187
8188        if (configChanged) {
8189            mWaitingForConfig = true;
8190            startFreezingDisplayLocked(false, 0, 0);
8191            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
8192        }
8193
8194        performLayoutAndPlaceSurfacesLocked();
8195    }
8196
8197    private void configureDisplayPolicyLocked(DisplayContent displayContent) {
8198        mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
8199                displayContent.mBaseDisplayWidth,
8200                displayContent.mBaseDisplayHeight,
8201                displayContent.mBaseDisplayDensity);
8202
8203        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8204        mPolicy.setDisplayOverscan(displayContent.getDisplay(),
8205                displayInfo.overscanLeft, displayInfo.overscanTop,
8206                displayInfo.overscanRight, displayInfo.overscanBottom);
8207    }
8208
8209    @Override
8210    public void setOverscan(int displayId, int left, int top, int right, int bottom) {
8211        if (mContext.checkCallingOrSelfPermission(
8212                android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
8213                PackageManager.PERMISSION_GRANTED) {
8214            throw new SecurityException("Must hold permission " +
8215                    android.Manifest.permission.WRITE_SECURE_SETTINGS);
8216        }
8217        final long ident = Binder.clearCallingIdentity();
8218        try {
8219            synchronized(mWindowMap) {
8220                DisplayContent displayContent = getDisplayContentLocked(displayId);
8221                if (displayContent != null) {
8222                    setOverscanLocked(displayContent, left, top, right, bottom);
8223                }
8224            }
8225        } finally {
8226            Binder.restoreCallingIdentity(ident);
8227        }
8228    }
8229
8230    private void setOverscanLocked(DisplayContent displayContent,
8231            int left, int top, int right, int bottom) {
8232        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8233        synchronized (displayContent.mDisplaySizeLock) {
8234            displayInfo.overscanLeft = left;
8235            displayInfo.overscanTop = top;
8236            displayInfo.overscanRight = right;
8237            displayInfo.overscanBottom = bottom;
8238        }
8239
8240        mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
8241        mDisplaySettings.writeSettingsLocked();
8242
8243        reconfigureDisplayLocked(displayContent);
8244    }
8245
8246    // -------------------------------------------------------------
8247    // Internals
8248    // -------------------------------------------------------------
8249
8250    final WindowState windowForClientLocked(Session session, IWindow client,
8251            boolean throwOnError) {
8252        return windowForClientLocked(session, client.asBinder(), throwOnError);
8253    }
8254
8255    final WindowState windowForClientLocked(Session session, IBinder client,
8256            boolean throwOnError) {
8257        WindowState win = mWindowMap.get(client);
8258        if (localLOGV) Slog.v(
8259            TAG, "Looking up client " + client + ": " + win);
8260        if (win == null) {
8261            RuntimeException ex = new IllegalArgumentException(
8262                    "Requested window " + client + " does not exist");
8263            if (throwOnError) {
8264                throw ex;
8265            }
8266            Slog.w(TAG, "Failed looking up window", ex);
8267            return null;
8268        }
8269        if (session != null && win.mSession != session) {
8270            RuntimeException ex = new IllegalArgumentException(
8271                    "Requested window " + client + " is in session " +
8272                    win.mSession + ", not " + session);
8273            if (throwOnError) {
8274                throw ex;
8275            }
8276            Slog.w(TAG, "Failed looking up window", ex);
8277            return null;
8278        }
8279
8280        return win;
8281    }
8282
8283    final void rebuildAppWindowListLocked() {
8284        rebuildAppWindowListLocked(getDefaultDisplayContentLocked());
8285    }
8286
8287    private void rebuildAppWindowListLocked(final DisplayContent displayContent) {
8288        final WindowList windows = displayContent.getWindowList();
8289        int NW = windows.size();
8290        int i;
8291        int lastBelow = -1;
8292        int numRemoved = 0;
8293
8294        if (mRebuildTmp.length < NW) {
8295            mRebuildTmp = new WindowState[NW+10];
8296        }
8297
8298        // First remove all existing app windows.
8299        i=0;
8300        while (i < NW) {
8301            WindowState w = windows.get(i);
8302            if (w.mAppToken != null) {
8303                WindowState win = windows.remove(i);
8304                win.mRebuilding = true;
8305                mRebuildTmp[numRemoved] = win;
8306                mWindowsChanged = true;
8307                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Rebuild removing window: " + win);
8308                NW--;
8309                numRemoved++;
8310                continue;
8311            } else if (lastBelow == i-1) {
8312                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8313                    lastBelow = i;
8314                }
8315            }
8316            i++;
8317        }
8318
8319        // Keep whatever windows were below the app windows still below,
8320        // by skipping them.
8321        lastBelow++;
8322        i = lastBelow;
8323
8324        // First add all of the exiting app tokens...  these are no longer
8325        // in the main app list, but still have windows shown.  We put them
8326        // in the back because now that the animation is over we no longer
8327        // will care about them.
8328        final ArrayList<TaskStack> stacks = displayContent.getStacks();
8329        final int numStacks = stacks.size();
8330        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8331            AppTokenList exitingAppTokens = stacks.get(stackNdx).mExitingAppTokens;
8332            int NT = exitingAppTokens.size();
8333            for (int j = 0; j < NT; j++) {
8334                i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
8335            }
8336        }
8337
8338        // And add in the still active app tokens in Z order.
8339        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
8340            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
8341            final int numTasks = tasks.size();
8342            for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
8343                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
8344                final int numTokens = tokens.size();
8345                for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
8346                    final AppWindowToken wtoken = tokens.get(tokenNdx);
8347                    if (wtoken.mDeferRemoval) {
8348                        continue;
8349                    }
8350                    i = reAddAppWindowsLocked(displayContent, i, wtoken);
8351                }
8352            }
8353        }
8354
8355        i -= lastBelow;
8356        if (i != numRemoved) {
8357            Slog.w(TAG, "On display=" + displayContent.getDisplayId() + " Rebuild removed " +
8358                    numRemoved + " windows but added " + i,
8359                    new RuntimeException("here").fillInStackTrace());
8360            for (i=0; i<numRemoved; i++) {
8361                WindowState ws = mRebuildTmp[i];
8362                if (ws.mRebuilding) {
8363                    StringWriter sw = new StringWriter();
8364                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
8365                    ws.dump(pw, "", true);
8366                    pw.flush();
8367                    Slog.w(TAG, "This window was lost: " + ws);
8368                    Slog.w(TAG, sw.toString());
8369                    ws.mWinAnimator.destroySurfaceLocked();
8370                }
8371            }
8372            Slog.w(TAG, "Current app token list:");
8373            dumpAppTokensLocked();
8374            Slog.w(TAG, "Final window list:");
8375            dumpWindowsLocked();
8376        }
8377    }
8378
8379    private final void assignLayersLocked(WindowList windows) {
8380        int N = windows.size();
8381        int curBaseLayer = 0;
8382        int curLayer = 0;
8383        int i;
8384
8385        if (DEBUG_LAYERS) Slog.v(TAG, "Assigning layers based on windows=" + windows,
8386                new RuntimeException("here").fillInStackTrace());
8387
8388        boolean anyLayerChanged = false;
8389
8390        for (i=0; i<N; i++) {
8391            final WindowState w = windows.get(i);
8392            final WindowStateAnimator winAnimator = w.mWinAnimator;
8393            boolean layerChanged = false;
8394            int oldLayer = w.mLayer;
8395            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8396                    || (i > 0 && w.mIsWallpaper)) {
8397                curLayer += WINDOW_LAYER_MULTIPLIER;
8398                w.mLayer = curLayer;
8399            } else {
8400                curBaseLayer = curLayer = w.mBaseLayer;
8401                w.mLayer = curLayer;
8402            }
8403            if (w.mLayer != oldLayer) {
8404                layerChanged = true;
8405                anyLayerChanged = true;
8406            }
8407            final AppWindowToken wtoken = w.mAppToken;
8408            oldLayer = winAnimator.mAnimLayer;
8409            if (w.mTargetAppToken != null) {
8410                winAnimator.mAnimLayer =
8411                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
8412            } else if (wtoken != null) {
8413                winAnimator.mAnimLayer =
8414                        w.mLayer + wtoken.mAppAnimator.animLayerAdjustment;
8415            } else {
8416                winAnimator.mAnimLayer = w.mLayer;
8417            }
8418            if (w.mIsImWindow) {
8419                winAnimator.mAnimLayer += mInputMethodAnimLayerAdjustment;
8420            } else if (w.mIsWallpaper) {
8421                winAnimator.mAnimLayer += mWallpaperAnimLayerAdjustment;
8422            }
8423            if (winAnimator.mAnimLayer != oldLayer) {
8424                layerChanged = true;
8425                anyLayerChanged = true;
8426            }
8427            if (layerChanged && w.getStack().isDimming(winAnimator)) {
8428                // Force an animation pass just to update the mDimLayer layer.
8429                scheduleAnimationLocked();
8430            }
8431            if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
8432                    + "mBase=" + w.mBaseLayer
8433                    + " mLayer=" + w.mLayer
8434                    + (wtoken == null ?
8435                            "" : " mAppLayer=" + wtoken.mAppAnimator.animLayerAdjustment)
8436                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
8437            //System.out.println(
8438            //    "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8439        }
8440
8441        //TODO (multidisplay): Magnification is supported only for the default display.
8442        if (mAccessibilityController != null && anyLayerChanged
8443                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
8444            mAccessibilityController.onWindowLayersChangedLocked();
8445        }
8446    }
8447
8448    private final void performLayoutAndPlaceSurfacesLocked() {
8449        int loopCount = 6;
8450        do {
8451            mTraversalScheduled = false;
8452            performLayoutAndPlaceSurfacesLockedLoop();
8453            mH.removeMessages(H.DO_TRAVERSAL);
8454            loopCount--;
8455        } while (mTraversalScheduled && loopCount > 0);
8456        mInnerFields.mWallpaperActionPending = false;
8457    }
8458
8459    private boolean mInLayout = false;
8460    private final void performLayoutAndPlaceSurfacesLockedLoop() {
8461        if (mInLayout) {
8462            if (DEBUG) {
8463                throw new RuntimeException("Recursive call!");
8464            }
8465            Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
8466                    + Debug.getCallers(3));
8467            return;
8468        }
8469
8470        if (mWaitingForConfig) {
8471            // Our configuration has changed (most likely rotation), but we
8472            // don't yet have the complete configuration to report to
8473            // applications.  Don't do any window layout until we have it.
8474            return;
8475        }
8476
8477        if (!mDisplayReady) {
8478            // Not yet initialized, nothing to do.
8479            return;
8480        }
8481
8482        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
8483        mInLayout = true;
8484        boolean recoveringMemory = false;
8485
8486        try {
8487            if (mForceRemoves != null) {
8488                recoveringMemory = true;
8489                // Wait a little bit for things to settle down, and off we go.
8490                for (int i=0; i<mForceRemoves.size(); i++) {
8491                    WindowState ws = mForceRemoves.get(i);
8492                    Slog.i(TAG, "Force removing: " + ws);
8493                    removeWindowInnerLocked(ws.mSession, ws);
8494                }
8495                mForceRemoves = null;
8496                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
8497                Object tmp = new Object();
8498                synchronized (tmp) {
8499                    try {
8500                        tmp.wait(250);
8501                    } catch (InterruptedException e) {
8502                    }
8503                }
8504            }
8505        } catch (RuntimeException e) {
8506            Log.wtf(TAG, "Unhandled exception while force removing for memory", e);
8507        }
8508
8509        try {
8510            performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
8511
8512            mInLayout = false;
8513
8514            if (needsLayout()) {
8515                if (++mLayoutRepeatCount < 6) {
8516                    requestTraversalLocked();
8517                } else {
8518                    Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
8519                    mLayoutRepeatCount = 0;
8520                }
8521            } else {
8522                mLayoutRepeatCount = 0;
8523            }
8524
8525            if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
8526                mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
8527                mH.sendEmptyMessage(H.REPORT_WINDOWS_CHANGE);
8528            }
8529        } catch (RuntimeException e) {
8530            mInLayout = false;
8531            Log.wtf(TAG, "Unhandled exception while laying out windows", e);
8532        }
8533
8534        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
8535    }
8536
8537    private final void performLayoutLockedInner(final DisplayContent displayContent,
8538                                    boolean initial, boolean updateInputWindows) {
8539        if (!displayContent.layoutNeeded) {
8540            return;
8541        }
8542        displayContent.layoutNeeded = false;
8543        WindowList windows = displayContent.getWindowList();
8544        boolean isDefaultDisplay = displayContent.isDefaultDisplay;
8545
8546        DisplayInfo displayInfo = displayContent.getDisplayInfo();
8547        final int dw = displayInfo.logicalWidth;
8548        final int dh = displayInfo.logicalHeight;
8549
8550        final int NFW = mFakeWindows.size();
8551        for (int i=0; i<NFW; i++) {
8552            mFakeWindows.get(i).layout(dw, dh);
8553        }
8554
8555        final int N = windows.size();
8556        int i;
8557
8558        if (DEBUG_LAYOUT) {
8559            Slog.v(TAG, "-------------------------------------");
8560            Slog.v(TAG, "performLayout: needed="
8561                    + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
8562        }
8563
8564        WindowStateAnimator universeBackground = null;
8565
8566        mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
8567        if (isDefaultDisplay) {
8568            // Not needed on non-default displays.
8569            mSystemDecorLayer = mPolicy.getSystemDecorLayerLw();
8570            mScreenRect.set(0, 0, dw, dh);
8571        }
8572
8573        mPolicy.getContentRectLw(mTmpContentRect);
8574        displayContent.resize(mTmpContentRect);
8575
8576        int seq = mLayoutSeq+1;
8577        if (seq < 0) seq = 0;
8578        mLayoutSeq = seq;
8579
8580        boolean behindDream = false;
8581
8582        // First perform layout of any root windows (not attached
8583        // to another window).
8584        int topAttached = -1;
8585        for (i = N-1; i >= 0; i--) {
8586            final WindowState win = windows.get(i);
8587
8588            // Don't do layout of a window if it is not visible, or
8589            // soon won't be visible, to avoid wasting time and funky
8590            // changes while a window is animating away.
8591            final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
8592                    || win.isGoneForLayoutLw();
8593
8594            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
8595                Slog.v(TAG, "1ST PASS " + win
8596                        + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
8597                        + " mLayoutAttached=" + win.mLayoutAttached
8598                        + " screen changed=" + win.isConfigChanged());
8599                final AppWindowToken atoken = win.mAppToken;
8600                if (gone) Slog.v(TAG, "  GONE: mViewVisibility="
8601                        + win.mViewVisibility + " mRelayoutCalled="
8602                        + win.mRelayoutCalled + " hidden="
8603                        + win.mRootToken.hidden + " hiddenRequested="
8604                        + (atoken != null && atoken.hiddenRequested)
8605                        + " mAttachedHidden=" + win.mAttachedHidden);
8606                else Slog.v(TAG, "  VIS: mViewVisibility="
8607                        + win.mViewVisibility + " mRelayoutCalled="
8608                        + win.mRelayoutCalled + " hidden="
8609                        + win.mRootToken.hidden + " hiddenRequested="
8610                        + (atoken != null && atoken.hiddenRequested)
8611                        + " mAttachedHidden=" + win.mAttachedHidden);
8612            }
8613
8614            // If this view is GONE, then skip it -- keep the current
8615            // frame, and let the caller know so they can ignore it
8616            // if they want.  (We do the normal layout for INVISIBLE
8617            // windows, since that means "perform layout as normal,
8618            // just don't display").
8619            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
8620                    || ((win.isConfigChanged() || win.setInsetsChanged()) &&
8621                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
8622                            win.mAppToken != null && win.mAppToken.layoutConfigChanges))
8623                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
8624                if (!win.mLayoutAttached) {
8625                    if (initial) {
8626                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8627                        win.mContentChanged = false;
8628                    }
8629                    if (win.mAttrs.type == TYPE_DREAM) {
8630                        // Don't layout windows behind a dream, so that if it
8631                        // does stuff like hide the status bar we won't get a
8632                        // bad transition when it goes away.
8633                        behindDream = true;
8634                    }
8635                    win.mLayoutNeeded = false;
8636                    win.prelayout();
8637                    mPolicy.layoutWindowLw(win, null);
8638                    win.mLayoutSeq = seq;
8639                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8640                            + win.mFrame + " mContainingFrame="
8641                            + win.mContainingFrame + " mDisplayFrame="
8642                            + win.mDisplayFrame);
8643                } else {
8644                    if (topAttached < 0) topAttached = i;
8645                }
8646            }
8647            if (win.mViewVisibility == View.VISIBLE
8648                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
8649                    && universeBackground == null) {
8650                universeBackground = win.mWinAnimator;
8651            }
8652        }
8653
8654        if (mAnimator.mUniverseBackground  != universeBackground) {
8655            mFocusMayChange = true;
8656            mAnimator.mUniverseBackground = universeBackground;
8657        }
8658
8659        boolean attachedBehindDream = false;
8660
8661        // Now perform layout of attached windows, which usually
8662        // depend on the position of the window they are attached to.
8663        // XXX does not deal with windows that are attached to windows
8664        // that are themselves attached.
8665        for (i = topAttached; i >= 0; i--) {
8666            final WindowState win = windows.get(i);
8667
8668            if (win.mLayoutAttached) {
8669                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win
8670                        + " mHaveFrame=" + win.mHaveFrame
8671                        + " mViewVisibility=" + win.mViewVisibility
8672                        + " mRelayoutCalled=" + win.mRelayoutCalled);
8673                // If this view is GONE, then skip it -- keep the current
8674                // frame, and let the caller know so they can ignore it
8675                // if they want.  (We do the normal layout for INVISIBLE
8676                // windows, since that means "perform layout as normal,
8677                // just don't display").
8678                if (attachedBehindDream && mPolicy.canBeForceHidden(win, win.mAttrs)) {
8679                    continue;
8680                }
8681                if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8682                        || !win.mHaveFrame || win.mLayoutNeeded) {
8683                    if (initial) {
8684                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
8685                        win.mContentChanged = false;
8686                    }
8687                    win.mLayoutNeeded = false;
8688                    win.prelayout();
8689                    mPolicy.layoutWindowLw(win, win.mAttachedWindow);
8690                    win.mLayoutSeq = seq;
8691                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame="
8692                            + win.mFrame + " mContainingFrame="
8693                            + win.mContainingFrame + " mDisplayFrame="
8694                            + win.mDisplayFrame);
8695                }
8696            } else if (win.mAttrs.type == TYPE_DREAM) {
8697                // Don't layout windows behind a dream, so that if it
8698                // does stuff like hide the status bar we won't get a
8699                // bad transition when it goes away.
8700                attachedBehindDream = behindDream;
8701            }
8702        }
8703
8704        // Window frames may have changed.  Tell the input dispatcher about it.
8705        mInputMonitor.setUpdateInputWindowsNeededLw();
8706        if (updateInputWindows) {
8707            mInputMonitor.updateInputWindowsLw(false /*force*/);
8708        }
8709
8710        mPolicy.finishLayoutLw();
8711    }
8712
8713    void makeWindowFreezingScreenIfNeededLocked(WindowState w) {
8714        // If the screen is currently frozen or off, then keep
8715        // it frozen/off until this window draws at its new
8716        // orientation.
8717        if (!okToDisplay()) {
8718            if (DEBUG_ORIENTATION) Slog.v(TAG, "Changing surface while display frozen: " + w);
8719            w.mOrientationChanging = true;
8720            w.mLastFreezeDuration = 0;
8721            mInnerFields.mOrientationChangeComplete = false;
8722            if (!mWindowsFreezingScreen) {
8723                mWindowsFreezingScreen = true;
8724                // XXX should probably keep timeout from
8725                // when we first froze the display.
8726                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
8727                mH.sendEmptyMessageDelayed(H.WINDOW_FREEZE_TIMEOUT,
8728                        WINDOW_FREEZE_TIMEOUT_DURATION);
8729            }
8730        }
8731    }
8732
8733    /**
8734     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
8735     * @param windows List of windows on default display.
8736     * @return bitmap indicating if another pass through layout must be made.
8737     */
8738    public int handleAppTransitionReadyLocked(WindowList windows) {
8739        int changes = 0;
8740        int i;
8741        int NN = mOpeningApps.size();
8742        boolean goodToGo = true;
8743        if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8744                "Checking " + NN + " opening apps (frozen="
8745                + mDisplayFrozen + " timeout="
8746                + mAppTransition.isTimeout() + ")...");
8747        if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
8748            // If the display isn't frozen, wait to do anything until
8749            // all of the apps are ready.  Otherwise just go because
8750            // we'll unfreeze the display when everyone is ready.
8751            for (i=0; i<NN && goodToGo; i++) {
8752                AppWindowToken wtoken = mOpeningApps.valueAt(i);
8753                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8754                        "Check opening app=" + wtoken + ": allDrawn="
8755                        + wtoken.allDrawn + " startingDisplayed="
8756                        + wtoken.startingDisplayed + " startingMoved="
8757                        + wtoken.startingMoved);
8758                if (!wtoken.allDrawn && !wtoken.startingDisplayed
8759                        && !wtoken.startingMoved) {
8760                    goodToGo = false;
8761                }
8762            }
8763        }
8764        if (goodToGo) {
8765            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
8766            int transit = mAppTransition.getAppTransition();
8767            if (mSkipAppTransitionAnimation) {
8768                transit = AppTransition.TRANSIT_UNSET;
8769            }
8770            mAppTransition.goodToGo();
8771            mStartingIconInTransition = false;
8772            mSkipAppTransitionAnimation = false;
8773
8774            mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
8775
8776            rebuildAppWindowListLocked();
8777
8778            // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
8779            WindowState oldWallpaper =
8780                    mWallpaperTarget != null && mWallpaperTarget.mWinAnimator.isAnimating()
8781                        && !mWallpaperTarget.mWinAnimator.isDummyAnimation()
8782                    ? null : mWallpaperTarget;
8783
8784            mInnerFields.mWallpaperMayChange = false;
8785
8786            // The top-most window will supply the layout params,
8787            // and we will determine it below.
8788            LayoutParams animLp = null;
8789            int bestAnimLayer = -1;
8790            boolean fullscreenAnim = false;
8791            boolean voiceInteraction = false;
8792
8793            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8794                    "New wallpaper target=" + mWallpaperTarget
8795                    + ", oldWallpaper=" + oldWallpaper
8796                    + ", lower target=" + mLowerWallpaperTarget
8797                    + ", upper target=" + mUpperWallpaperTarget);
8798
8799            boolean openingAppHasWallpaper = false;
8800            boolean closingAppHasWallpaper = false;
8801            final AppWindowToken lowerWallpaperAppToken;
8802            final AppWindowToken upperWallpaperAppToken;
8803            if (mLowerWallpaperTarget == null) {
8804                lowerWallpaperAppToken = upperWallpaperAppToken = null;
8805            } else {
8806                lowerWallpaperAppToken = mLowerWallpaperTarget.mAppToken;
8807                upperWallpaperAppToken = mUpperWallpaperTarget.mAppToken;
8808            }
8809
8810            // Do a first pass through the tokens for two
8811            // things:
8812            // (1) Determine if both the closing and opening
8813            // app token sets are wallpaper targets, in which
8814            // case special animations are needed
8815            // (since the wallpaper needs to stay static
8816            // behind them).
8817            // (2) Find the layout params of the top-most
8818            // application window in the tokens, which is
8819            // what will control the animation theme.
8820            final int NC = mClosingApps.size();
8821            NN = NC + mOpeningApps.size();
8822            for (i=0; i<NN; i++) {
8823                final AppWindowToken wtoken;
8824                if (i < NC) {
8825                    wtoken = mClosingApps.valueAt(i);
8826                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8827                        closingAppHasWallpaper = true;
8828                    }
8829                } else {
8830                    wtoken = mOpeningApps.valueAt(i - NC);
8831                    if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
8832                        openingAppHasWallpaper = true;
8833                    }
8834                }
8835
8836                voiceInteraction |= wtoken.voiceInteraction;
8837
8838                if (wtoken.appFullscreen) {
8839                    WindowState ws = wtoken.findMainWindow();
8840                    if (ws != null) {
8841                        animLp = ws.mAttrs;
8842                        bestAnimLayer = ws.mLayer;
8843                        fullscreenAnim = true;
8844                    }
8845                } else if (!fullscreenAnim) {
8846                    WindowState ws = wtoken.findMainWindow();
8847                    if (ws != null) {
8848                        if (ws.mLayer > bestAnimLayer) {
8849                            animLp = ws.mAttrs;
8850                            bestAnimLayer = ws.mLayer;
8851                        }
8852                    }
8853                }
8854            }
8855
8856            mAnimateWallpaperWithTarget = false;
8857            if (closingAppHasWallpaper && openingAppHasWallpaper) {
8858                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Wallpaper animation!");
8859                switch (transit) {
8860                    case AppTransition.TRANSIT_ACTIVITY_OPEN:
8861                    case AppTransition.TRANSIT_TASK_OPEN:
8862                    case AppTransition.TRANSIT_TASK_TO_FRONT:
8863                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_OPEN;
8864                        break;
8865                    case AppTransition.TRANSIT_ACTIVITY_CLOSE:
8866                    case AppTransition.TRANSIT_TASK_CLOSE:
8867                    case AppTransition.TRANSIT_TASK_TO_BACK:
8868                        transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
8869                        break;
8870                }
8871                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
8872            } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
8873                    && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
8874                // We are transitioning from an activity with
8875                // a wallpaper to one without.
8876                transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
8877                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8878                        "New transit away from wallpaper: " + transit);
8879            } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
8880                // We are transitioning from an activity without
8881                // a wallpaper to now showing the wallpaper
8882                transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
8883                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8884                        "New transit into wallpaper: " + transit);
8885            } else {
8886                mAnimateWallpaperWithTarget = true;
8887            }
8888
8889            // If all closing windows are obscured, then there is
8890            // no need to do an animation.  This is the case, for
8891            // example, when this transition is being done behind
8892            // the lock screen.
8893            if (!mPolicy.allowAppAnimationsLw()) {
8894                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
8895                        "Animations disallowed by keyguard or dream.");
8896                animLp = null;
8897            }
8898
8899            AppWindowToken topOpeningApp = null;
8900            AppWindowToken topClosingApp = null;
8901            int topOpeningLayer = 0;
8902            int topClosingLayer = 0;
8903
8904            NN = mOpeningApps.size();
8905            for (i=0; i<NN; i++) {
8906                AppWindowToken wtoken = mOpeningApps.valueAt(i);
8907                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8908                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
8909                appAnimator.clearThumbnail();
8910                appAnimator.animation = null;
8911                wtoken.inPendingTransaction = false;
8912                setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
8913                wtoken.updateReportedVisibilityLocked();
8914                wtoken.waitingToShow = false;
8915
8916                appAnimator.mAllAppWinAnimators.clear();
8917                final int N = wtoken.allAppWindows.size();
8918                for (int j = 0; j < N; j++) {
8919                    appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
8920                }
8921                mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
8922
8923                if (animLp != null) {
8924                    int layer = -1;
8925                    for (int j=0; j<wtoken.windows.size(); j++) {
8926                        WindowState win = wtoken.windows.get(j);
8927                        if (win.mWinAnimator.mAnimLayer > layer) {
8928                            layer = win.mWinAnimator.mAnimLayer;
8929                        }
8930                    }
8931                    if (topOpeningApp == null || layer > topOpeningLayer) {
8932                        topOpeningApp = wtoken;
8933                        topOpeningLayer = layer;
8934                    }
8935                }
8936            }
8937            NN = mClosingApps.size();
8938            for (i=0; i<NN; i++) {
8939                AppWindowToken wtoken = mClosingApps.valueAt(i);
8940                final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
8941                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
8942                appAnimator.clearThumbnail();
8943                appAnimator.animation = null;
8944                wtoken.inPendingTransaction = false;
8945                setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
8946                wtoken.updateReportedVisibilityLocked();
8947                wtoken.waitingToHide = false;
8948                // Force the allDrawn flag, because we want to start
8949                // this guy's animations regardless of whether it's
8950                // gotten drawn.
8951                wtoken.allDrawn = true;
8952                wtoken.deferClearAllDrawn = false;
8953
8954                if (animLp != null) {
8955                    int layer = -1;
8956                    for (int j=0; j<wtoken.windows.size(); j++) {
8957                        WindowState win = wtoken.windows.get(j);
8958                        if (win.mWinAnimator.mAnimLayer > layer) {
8959                            layer = win.mWinAnimator.mAnimLayer;
8960                        }
8961                    }
8962                    if (topClosingApp == null || layer > topClosingLayer) {
8963                        topClosingApp = wtoken;
8964                        topClosingLayer = layer;
8965                    }
8966                }
8967            }
8968
8969            AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
8970                    topOpeningApp.mAppAnimator;
8971            AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
8972                    topClosingApp.mAppAnimator;
8973            Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
8974            if (nextAppTransitionThumbnail != null
8975                    && openingAppAnimator != null && openingAppAnimator.animation != null &&
8976                    nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
8977                // This thumbnail animation is very special, we need to have
8978                // an extra surface with the thumbnail included with the animation.
8979                Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
8980                        nextAppTransitionThumbnail.getHeight());
8981                try {
8982                    // TODO(multi-display): support other displays
8983                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
8984                    final Display display = displayContent.getDisplay();
8985                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
8986
8987                    // Create a new surface for the thumbnail
8988                    SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
8989                            "thumbnail anim", dirty.width(), dirty.height(),
8990                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
8991                    surfaceControl.setLayerStack(display.getLayerStack());
8992                    if (SHOW_TRANSACTIONS) {
8993                        Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
8994                    }
8995
8996                    // Draw the thumbnail onto the surface
8997                    Surface drawSurface = new Surface();
8998                    drawSurface.copyFrom(surfaceControl);
8999                    Canvas c = drawSurface.lockCanvas(dirty);
9000                    c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
9001                    drawSurface.unlockCanvasAndPost(c);
9002                    drawSurface.release();
9003
9004                    // Get the thumbnail animation
9005                    Animation anim;
9006                    if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
9007                        // For the new aspect-scaled transition, we want it to always show
9008                        // above the animating opening/closing window, and we want to
9009                        // synchronize its thumbnail surface with the surface for the
9010                        // open/close animation (only on the way down)
9011                        anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
9012                                displayInfo.appWidth, displayInfo.appHeight,
9013                                displayInfo.logicalWidth, transit);
9014                        openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
9015                                topClosingLayer);
9016                        openingAppAnimator.deferThumbnailDestruction =
9017                                !mAppTransition.isNextThumbnailTransitionScaleUp();
9018                        if (openingAppAnimator.deferThumbnailDestruction) {
9019                            if (closingAppAnimator != null &&
9020                                    closingAppAnimator.animation != null) {
9021                                closingAppAnimator.deferredThumbnail = surfaceControl;
9022                            }
9023                        }
9024                    } else {
9025                        anim = mAppTransition.createThumbnailScaleAnimationLocked(
9026                                displayInfo.appWidth, displayInfo.appHeight, transit);
9027                    }
9028                    anim.restrictDuration(MAX_ANIMATION_DURATION);
9029                    anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
9030
9031                    openingAppAnimator.thumbnail = surfaceControl;
9032                    openingAppAnimator.thumbnailLayer = topOpeningLayer;
9033                    openingAppAnimator.thumbnailAnimation = anim;
9034                    openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
9035                    openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
9036                } catch (OutOfResourcesException e) {
9037                    Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
9038                            + " h=" + dirty.height(), e);
9039                    openingAppAnimator.clearThumbnail();
9040                }
9041            }
9042
9043            mAppTransition.postAnimationCallback();
9044            mAppTransition.clear();
9045
9046            mOpeningApps.clear();
9047            mClosingApps.clear();
9048
9049            // This has changed the visibility of windows, so perform
9050            // a new layout to get them all up-to-date.
9051            changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT
9052                    | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
9053            getDefaultDisplayContentLocked().layoutNeeded = true;
9054
9055            // TODO(multidisplay): IMEs are only supported on the default display.
9056            if (windows == getDefaultWindowListLocked()
9057                    && !moveInputMethodWindowsIfNeededLocked(true)) {
9058                assignLayersLocked(windows);
9059            }
9060            updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
9061            mFocusMayChange = false;
9062        }
9063
9064        return changes;
9065    }
9066
9067    /**
9068     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9069     * @return bitmap indicating if another pass through layout must be made.
9070     */
9071    private int handleAnimatingStoppedAndTransitionLocked() {
9072        int changes = 0;
9073
9074        mAppTransition.setIdle();
9075        // Restore window app tokens to the ActivityManager views
9076        ArrayList<TaskStack> stacks = getDefaultDisplayContentLocked().getStacks();
9077        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9078            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9079            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9080                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9081                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9082                    tokens.get(tokenNdx).sendingToBottom = false;
9083                }
9084            }
9085        }
9086        rebuildAppWindowListLocked();
9087
9088        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
9089        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9090                "Wallpaper layer changed: assigning layers + relayout");
9091        moveInputMethodWindowsIfNeededLocked(true);
9092        mInnerFields.mWallpaperMayChange = true;
9093        // Since the window list has been rebuilt, focus might
9094        // have to be recomputed since the actual order of windows
9095        // might have changed again.
9096        mFocusMayChange = true;
9097
9098        return changes;
9099    }
9100
9101    private void updateResizingWindows(final WindowState w) {
9102        final WindowStateAnimator winAnimator = w.mWinAnimator;
9103        if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) {
9104            w.setInsetsChanged();
9105            boolean configChanged = w.isConfigChanged();
9106            if (DEBUG_CONFIGURATION && configChanged) {
9107                Slog.v(TAG, "Win " + w + " config changed: "
9108                        + mCurConfiguration);
9109            }
9110            if (localLOGV) Slog.v(TAG, "Resizing " + w
9111                    + ": configChanged=" + configChanged
9112                    + " last=" + w.mLastFrame + " frame=" + w.mFrame);
9113            w.mLastFrame.set(w.mFrame);
9114            if (w.mContentInsetsChanged
9115                    || w.mVisibleInsetsChanged
9116                    || winAnimator.mSurfaceResized
9117                    || configChanged) {
9118                if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
9119                    Slog.v(TAG, "Resize reasons for w=" + w + ": "
9120                            + " contentInsetsChanged=" + w.mContentInsetsChanged
9121                            + " " + w.mContentInsets.toShortString()
9122                            + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
9123                            + " " + w.mVisibleInsets.toShortString()
9124                            + " stableInsetsChanged=" + w.mStableInsetsChanged
9125                            + " " + w.mStableInsets.toShortString()
9126                            + " surfaceResized=" + winAnimator.mSurfaceResized
9127                            + " configChanged=" + configChanged);
9128                }
9129
9130                w.mLastOverscanInsets.set(w.mOverscanInsets);
9131                w.mLastContentInsets.set(w.mContentInsets);
9132                w.mLastVisibleInsets.set(w.mVisibleInsets);
9133                w.mLastStableInsets.set(w.mStableInsets);
9134                makeWindowFreezingScreenIfNeededLocked(w);
9135                // If the orientation is changing, then we need to
9136                // hold off on unfreezing the display until this
9137                // window has been redrawn; to do that, we need
9138                // to go through the process of getting informed
9139                // by the application when it has finished drawing.
9140                if (w.mOrientationChanging) {
9141                    if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
9142                            "Orientation start waiting for draw mDrawState=DRAW_PENDING in "
9143                            + w + ", surface " + winAnimator.mSurfaceControl);
9144                    winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
9145                    if (w.mAppToken != null) {
9146                        w.mAppToken.allDrawn = false;
9147                        w.mAppToken.deferClearAllDrawn = false;
9148                    }
9149                }
9150                if (!mResizingWindows.contains(w)) {
9151                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
9152                            "Resizing window " + w + " to " + winAnimator.mSurfaceW
9153                            + "x" + winAnimator.mSurfaceH);
9154                    mResizingWindows.add(w);
9155                }
9156            } else if (w.mOrientationChanging) {
9157                if (w.isDrawnLw()) {
9158                    if (DEBUG_ORIENTATION) Slog.v(TAG,
9159                            "Orientation not waiting for draw in "
9160                            + w + ", surface " + winAnimator.mSurfaceControl);
9161                    w.mOrientationChanging = false;
9162                    w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
9163                            - mDisplayFreezeTime);
9164                }
9165            }
9166        }
9167    }
9168
9169    /**
9170     * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
9171     *
9172     * @param w WindowState this method is applied to.
9173     * @param currentTime The time which animations use for calculating transitions.
9174     * @param innerDw Width of app window.
9175     * @param innerDh Height of app window.
9176     */
9177    private void handleNotObscuredLocked(final WindowState w, final long currentTime,
9178                                         final int innerDw, final int innerDh) {
9179        final WindowManager.LayoutParams attrs = w.mAttrs;
9180        final int attrFlags = attrs.flags;
9181        final boolean canBeSeen = w.isDisplayedLw();
9182        final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
9183
9184        if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
9185            // This window completely covers everything behind it,
9186            // so we want to leave all of them as undimmed (for
9187            // performance reasons).
9188            mInnerFields.mObscured = true;
9189        }
9190
9191        if (w.mHasSurface) {
9192            if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
9193                mInnerFields.mHoldScreen = w.mSession;
9194            }
9195            if (!mInnerFields.mSyswin && w.mAttrs.screenBrightness >= 0
9196                    && mInnerFields.mScreenBrightness < 0) {
9197                mInnerFields.mScreenBrightness = w.mAttrs.screenBrightness;
9198            }
9199            if (!mInnerFields.mSyswin && w.mAttrs.buttonBrightness >= 0
9200                    && mInnerFields.mButtonBrightness < 0) {
9201                mInnerFields.mButtonBrightness = w.mAttrs.buttonBrightness;
9202            }
9203            if (!mInnerFields.mSyswin && w.mAttrs.userActivityTimeout >= 0
9204                    && mInnerFields.mUserActivityTimeout < 0) {
9205                mInnerFields.mUserActivityTimeout = w.mAttrs.userActivityTimeout;
9206            }
9207
9208            final int type = attrs.type;
9209            if (canBeSeen
9210                    && (type == TYPE_SYSTEM_DIALOG
9211                     || type == TYPE_RECENTS_OVERLAY
9212                     || type == TYPE_SYSTEM_ERROR
9213                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
9214                mInnerFields.mSyswin = true;
9215            }
9216
9217            if (canBeSeen) {
9218                // This function assumes that the contents of the default display are
9219                // processed first before secondary displays.
9220                final DisplayContent displayContent = w.getDisplayContent();
9221                if (displayContent != null && displayContent.isDefaultDisplay) {
9222                    // While a dream or keyguard is showing, obscure ordinary application
9223                    // content on secondary displays (by forcibly enabling mirroring unless
9224                    // there is other content we want to show) but still allow opaque
9225                    // keyguard dialogs to be shown.
9226                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
9227                        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
9228                    }
9229                    mInnerFields.mDisplayHasContent = true;
9230                } else if (displayContent != null &&
9231                        (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays
9232                        || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG))) {
9233                    // Allow full screen keyguard presentation dialogs to be seen.
9234                    mInnerFields.mDisplayHasContent = true;
9235                }
9236                if (mInnerFields.mPreferredRefreshRate == 0
9237                        && w.mAttrs.preferredRefreshRate != 0) {
9238                    mInnerFields.mPreferredRefreshRate = w.mAttrs.preferredRefreshRate;
9239                }
9240            }
9241        }
9242    }
9243
9244    private void handleFlagDimBehind(WindowState w) {
9245        final WindowManager.LayoutParams attrs = w.mAttrs;
9246        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
9247                && w.isDisplayedLw()
9248                && !w.mExiting) {
9249            final WindowStateAnimator winAnimator = w.mWinAnimator;
9250            final TaskStack stack = w.getStack();
9251            stack.setDimmingTag();
9252            if (!stack.isDimming(winAnimator)) {
9253                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
9254                stack.startDimmingIfNeeded(winAnimator);
9255            }
9256        }
9257    }
9258
9259    private void updateAllDrawnLocked(DisplayContent displayContent) {
9260        // See if any windows have been drawn, so they (and others
9261        // associated with them) can now be shown.
9262        ArrayList<TaskStack> stacks = displayContent.getStacks();
9263        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
9264            final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
9265            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
9266                final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
9267                for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9268                    final AppWindowToken wtoken = tokens.get(tokenNdx);
9269                    if (!wtoken.allDrawn) {
9270                        int numInteresting = wtoken.numInterestingWindows;
9271                        if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9272                            if (DEBUG_VISIBILITY) Slog.v(TAG,
9273                                    "allDrawn: " + wtoken
9274                                    + " interesting=" + numInteresting
9275                                    + " drawn=" + wtoken.numDrawnWindows);
9276                            wtoken.allDrawn = true;
9277                            mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
9278                        }
9279                    }
9280                }
9281            }
9282        }
9283    }
9284
9285    // "Something has changed!  Let's make it correct now."
9286    private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) {
9287        if (DEBUG_WINDOW_TRACE) {
9288            Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by "
9289                    + Debug.getCallers(3));
9290        }
9291
9292        final long currentTime = SystemClock.uptimeMillis();
9293
9294        int i;
9295        boolean updateInputWindowsNeeded = false;
9296
9297        if (mFocusMayChange) {
9298            mFocusMayChange = false;
9299            updateInputWindowsNeeded = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
9300                    false /*updateInputWindows*/);
9301        }
9302
9303        // Initialize state of exiting tokens.
9304        final int numDisplays = mDisplayContents.size();
9305        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9306            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9307            for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
9308                displayContent.mExitingTokens.get(i).hasVisible = false;
9309            }
9310        }
9311
9312        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9313            // Initialize state of exiting applications.
9314            final AppTokenList exitingAppTokens =
9315                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9316            for (int tokenNdx = exitingAppTokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
9317                exitingAppTokens.get(tokenNdx).hasVisible = false;
9318            }
9319        }
9320
9321        mInnerFields.mHoldScreen = null;
9322        mInnerFields.mScreenBrightness = -1;
9323        mInnerFields.mButtonBrightness = -1;
9324        mInnerFields.mUserActivityTimeout = -1;
9325        mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false;
9326
9327        mTransactionSequence++;
9328
9329        final DisplayContent defaultDisplay = getDefaultDisplayContentLocked();
9330        final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo();
9331        final int defaultDw = defaultInfo.logicalWidth;
9332        final int defaultDh = defaultInfo.logicalHeight;
9333
9334        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9335                ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
9336        SurfaceControl.openTransaction();
9337        try {
9338
9339            if (mWatermark != null) {
9340                mWatermark.positionSurface(defaultDw, defaultDh);
9341            }
9342            if (mStrictModeFlash != null) {
9343                mStrictModeFlash.positionSurface(defaultDw, defaultDh);
9344            }
9345            if (mCircularDisplayMask != null) {
9346                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
9347            }
9348
9349            boolean focusDisplayed = false;
9350
9351            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9352                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9353                boolean updateAllDrawn = false;
9354                WindowList windows = displayContent.getWindowList();
9355                DisplayInfo displayInfo = displayContent.getDisplayInfo();
9356                final int displayId = displayContent.getDisplayId();
9357                final int dw = displayInfo.logicalWidth;
9358                final int dh = displayInfo.logicalHeight;
9359                final int innerDw = displayInfo.appWidth;
9360                final int innerDh = displayInfo.appHeight;
9361                final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
9362
9363                // Reset for each display.
9364                mInnerFields.mDisplayHasContent = false;
9365                mInnerFields.mPreferredRefreshRate = 0;
9366
9367                int repeats = 0;
9368                do {
9369                    repeats++;
9370                    if (repeats > 6) {
9371                        Slog.w(TAG, "Animation repeat aborted after too many iterations");
9372                        displayContent.layoutNeeded = false;
9373                        break;
9374                    }
9375
9376                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
9377                        displayContent.pendingLayoutChanges);
9378
9379                    if ((displayContent.pendingLayoutChanges &
9380                            WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
9381                            (adjustWallpaperWindowsLocked() &
9382                                    ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9383                        assignLayersLocked(windows);
9384                        displayContent.layoutNeeded = true;
9385                    }
9386
9387                    if (isDefaultDisplay && (displayContent.pendingLayoutChanges
9388                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9389                        if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9390                        if (updateOrientationFromAppTokensLocked(true)) {
9391                            displayContent.layoutNeeded = true;
9392                            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9393                        }
9394                    }
9395
9396                    if ((displayContent.pendingLayoutChanges
9397                            & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9398                        displayContent.layoutNeeded = true;
9399                    }
9400
9401                    // FIRST LOOP: Perform a layout, if needed.
9402                    if (repeats < 4) {
9403                        performLayoutLockedInner(displayContent, repeats == 1,
9404                                false /*updateInputWindows*/);
9405                    } else {
9406                        Slog.w(TAG, "Layout repeat skipped after too many iterations");
9407                    }
9408
9409                    // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
9410                    // it is animating.
9411                    displayContent.pendingLayoutChanges = 0;
9412
9413                    if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
9414                            + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
9415
9416                    if (isDefaultDisplay) {
9417                        mPolicy.beginPostLayoutPolicyLw(dw, dh);
9418                        for (i = windows.size() - 1; i >= 0; i--) {
9419                            WindowState w = windows.get(i);
9420                            if (w.mHasSurface) {
9421                                mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs);
9422                            }
9423                        }
9424                        displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw();
9425                        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats(
9426                            "after finishPostLayoutPolicyLw", displayContent.pendingLayoutChanges);
9427                    }
9428                } while (displayContent.pendingLayoutChanges != 0);
9429
9430                mInnerFields.mObscured = false;
9431                mInnerFields.mSyswin = false;
9432                displayContent.resetDimming();
9433
9434                // Only used if default window
9435                final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
9436
9437                final int N = windows.size();
9438                for (i=N-1; i>=0; i--) {
9439                    WindowState w = windows.get(i);
9440                    final TaskStack stack = w.getStack();
9441                    if (stack == null) {
9442                        continue;
9443                    }
9444
9445                    final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured;
9446
9447                    // Update effect.
9448                    w.mObscured = mInnerFields.mObscured;
9449                    if (!mInnerFields.mObscured) {
9450                        handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
9451                    }
9452
9453                    if (!stack.testDimmingTag()) {
9454                        handleFlagDimBehind(w);
9455                    }
9456
9457                    if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
9458                            && w.isVisibleLw()) {
9459                        // This is the wallpaper target and its obscured state
9460                        // changed... make sure the current wallaper's visibility
9461                        // has been updated accordingly.
9462                        updateWallpaperVisibilityLocked();
9463                    }
9464
9465                    final WindowStateAnimator winAnimator = w.mWinAnimator;
9466
9467                    // If the window has moved due to its containing
9468                    // content frame changing, then we'd like to animate
9469                    // it.
9470                    if (w.mHasSurface && w.shouldAnimateMove()) {
9471                        // Frame has moved, containing content frame
9472                        // has also moved, and we're not currently animating...
9473                        // let's do something.
9474                        Animation a = AnimationUtils.loadAnimation(mContext,
9475                                com.android.internal.R.anim.window_move_from_decor);
9476                        winAnimator.setAnimation(a);
9477                        winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
9478                        winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
9479
9480                        //TODO (multidisplay): Accessibility supported only for the default display.
9481                        if (mAccessibilityController != null
9482                                && displayId == Display.DEFAULT_DISPLAY) {
9483                            mAccessibilityController.onSomeWindowResizedOrMovedLocked();
9484                        }
9485
9486                        try {
9487                            w.mClient.moved(w.mFrame.left, w.mFrame.top);
9488                        } catch (RemoteException e) {
9489                        }
9490                    }
9491
9492                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
9493                    w.mContentChanged = false;
9494
9495                    // Moved from updateWindowsAndWallpaperLocked().
9496                    if (w.mHasSurface) {
9497                        // Take care of the window being ready to display.
9498                        final boolean committed =
9499                                winAnimator.commitFinishDrawingLocked(currentTime);
9500                        if (isDefaultDisplay && committed) {
9501                            if (w.mAttrs.type == TYPE_DREAM) {
9502                                // HACK: When a dream is shown, it may at that
9503                                // point hide the lock screen.  So we need to
9504                                // redo the layout to let the phone window manager
9505                                // make this happen.
9506                                displayContent.pendingLayoutChanges |=
9507                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9508                                if (DEBUG_LAYOUT_REPEATS) {
9509                                    debugLayoutRepeats(
9510                                        "dream and commitFinishDrawingLocked true",
9511                                        displayContent.pendingLayoutChanges);
9512                                }
9513                            }
9514                            if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
9515                                if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
9516                                        "First draw done in potential wallpaper target " + w);
9517                                mInnerFields.mWallpaperMayChange = true;
9518                                displayContent.pendingLayoutChanges |=
9519                                        WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9520                                if (DEBUG_LAYOUT_REPEATS) {
9521                                    debugLayoutRepeats(
9522                                        "wallpaper and commitFinishDrawingLocked true",
9523                                        displayContent.pendingLayoutChanges);
9524                                }
9525                            }
9526                        }
9527
9528                        winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
9529
9530                        final AppWindowToken atoken = w.mAppToken;
9531                        if (DEBUG_STARTING_WINDOW && atoken != null
9532                                && w == atoken.startingWindow) {
9533                            Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen="
9534                                + w.isOnScreen() + " allDrawn=" + atoken.allDrawn
9535                                + " freezingScreen=" + atoken.mAppAnimator.freezingScreen);
9536                        }
9537                        if (atoken != null
9538                                && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
9539                            if (atoken.lastTransactionSequence != mTransactionSequence) {
9540                                atoken.lastTransactionSequence = mTransactionSequence;
9541                                atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9542                                atoken.startingDisplayed = false;
9543                            }
9544                            if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
9545                                    && !w.mExiting && !w.mDestroying) {
9546                                if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9547                                    Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
9548                                            + ", isAnimating=" + winAnimator.isAnimating());
9549                                    if (!w.isDrawnLw()) {
9550                                        Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
9551                                                + " pv=" + w.mPolicyVisibility
9552                                                + " mDrawState=" + winAnimator.mDrawState
9553                                                + " ah=" + w.mAttachedHidden
9554                                                + " th=" + atoken.hiddenRequested
9555                                                + " a=" + winAnimator.mAnimating);
9556                                    }
9557                                }
9558                                if (w != atoken.startingWindow) {
9559                                    if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
9560                                        atoken.numInterestingWindows++;
9561                                        if (w.isDrawnLw()) {
9562                                            atoken.numDrawnWindows++;
9563                                            if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
9564                                                    "tokenMayBeDrawn: " + atoken
9565                                                    + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
9566                                                    + " mAppFreezing=" + w.mAppFreezing);
9567                                            updateAllDrawn = true;
9568                                        }
9569                                    }
9570                                } else if (w.isDrawnLw()) {
9571                                    atoken.startingDisplayed = true;
9572                                }
9573                            }
9574                        }
9575                    }
9576
9577                    if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus)
9578                            && w.isDisplayedLw()) {
9579                        focusDisplayed = true;
9580                    }
9581
9582                    updateResizingWindows(w);
9583                }
9584
9585                mDisplayManagerInternal.setDisplayProperties(displayId,
9586                        mInnerFields.mDisplayHasContent, mInnerFields.mPreferredRefreshRate,
9587                        true /* inTraversal, must call performTraversalInTrans... below */);
9588
9589                getDisplayContentLocked(displayId).stopDimmingIfNeeded();
9590
9591                if (updateAllDrawn) {
9592                    updateAllDrawnLocked(displayContent);
9593                }
9594            }
9595
9596            if (focusDisplayed) {
9597                mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9598            }
9599
9600            // Give the display manager a chance to adjust properties
9601            // like display rotation if it needs to.
9602            mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
9603
9604        } catch (RuntimeException e) {
9605            Log.wtf(TAG, "Unhandled exception in Window Manager", e);
9606        } finally {
9607            SurfaceControl.closeTransaction();
9608            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
9609                    "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
9610        }
9611
9612        final WindowList defaultWindows = defaultDisplay.getWindowList();
9613
9614        // If we are ready to perform an app transition, check through
9615        // all of the app tokens to be shown and see if they are ready
9616        // to go.
9617        if (mAppTransition.isReady()) {
9618            defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows);
9619            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
9620                    defaultDisplay.pendingLayoutChanges);
9621        }
9622
9623        if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
9624            // We have finished the animation of an app transition.  To do
9625            // this, we have delayed a lot of operations like showing and
9626            // hiding apps, moving apps in Z-order, etc.  The app token list
9627            // reflects the correct Z-order, but the window list may now
9628            // be out of sync with it.  So here we will just rebuild the
9629            // entire app window list.  Fun!
9630            defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
9631            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
9632                defaultDisplay.pendingLayoutChanges);
9633        }
9634
9635        if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0
9636                && !mAppTransition.isReady()) {
9637            // At this point, there was a window with a wallpaper that
9638            // was force hiding other windows behind it, but now it
9639            // is going away.  This may be simple -- just animate
9640            // away the wallpaper and its window -- or it may be
9641            // hard -- the wallpaper now needs to be shown behind
9642            // something that was hidden.
9643            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9644            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
9645                defaultDisplay.pendingLayoutChanges);
9646        }
9647        mInnerFields.mWallpaperForceHidingChanged = false;
9648
9649        if (mInnerFields.mWallpaperMayChange) {
9650            if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "Wallpaper may change!  Adjusting");
9651            defaultDisplay.pendingLayoutChanges |=
9652                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9653            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("WallpaperMayChange",
9654                    defaultDisplay.pendingLayoutChanges);
9655        }
9656
9657        if (mFocusMayChange) {
9658            mFocusMayChange = false;
9659            if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
9660                    false /*updateInputWindows*/)) {
9661                updateInputWindowsNeeded = true;
9662                defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
9663            }
9664        }
9665
9666        if (needsLayout()) {
9667            defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
9668            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded",
9669                    defaultDisplay.pendingLayoutChanges);
9670        }
9671
9672        for (i = mResizingWindows.size() - 1; i >= 0; i--) {
9673            WindowState win = mResizingWindows.get(i);
9674            if (win.mAppFreezing) {
9675                // Don't remove this window until rotation has completed.
9676                continue;
9677            }
9678            win.reportResized();
9679            mResizingWindows.remove(i);
9680        }
9681
9682        if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
9683                "With display frozen, orientationChangeComplete="
9684                + mInnerFields.mOrientationChangeComplete);
9685        if (mInnerFields.mOrientationChangeComplete) {
9686            if (mWindowsFreezingScreen) {
9687                mWindowsFreezingScreen = false;
9688                mLastFinishedFreezeSource = mInnerFields.mLastWindowFreezeSource;
9689                mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9690            }
9691            stopFreezingDisplayLocked();
9692        }
9693
9694        // Destroy the surface of any windows that are no longer visible.
9695        boolean wallpaperDestroyed = false;
9696        i = mDestroySurface.size();
9697        if (i > 0) {
9698            do {
9699                i--;
9700                WindowState win = mDestroySurface.get(i);
9701                win.mDestroying = false;
9702                if (mInputMethodWindow == win) {
9703                    mInputMethodWindow = null;
9704                }
9705                if (win == mWallpaperTarget) {
9706                    wallpaperDestroyed = true;
9707                }
9708                win.mWinAnimator.destroySurfaceLocked();
9709            } while (i > 0);
9710            mDestroySurface.clear();
9711        }
9712
9713        // Time to remove any exiting tokens?
9714        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9715            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9716            ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
9717            for (i = exitingTokens.size() - 1; i >= 0; i--) {
9718                WindowToken token = exitingTokens.get(i);
9719                if (!token.hasVisible) {
9720                    exitingTokens.remove(i);
9721                    if (token.windowType == TYPE_WALLPAPER) {
9722                        mWallpaperTokens.remove(token);
9723                    }
9724                }
9725            }
9726        }
9727
9728        // Time to remove any exiting applications?
9729        for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; --stackNdx) {
9730            // Initialize state of exiting applications.
9731            final AppTokenList exitingAppTokens =
9732                    mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
9733            for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
9734                AppWindowToken token = exitingAppTokens.get(i);
9735                if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
9736                    // Make sure there is no animation running on this token,
9737                    // so any windows associated with it will be removed as
9738                    // soon as their animations are complete
9739                    token.mAppAnimator.clearAnimation();
9740                    token.mAppAnimator.animating = false;
9741                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
9742                            "performLayout: App token exiting now removed" + token);
9743                    removeAppFromTaskLocked(token);
9744                    exitingAppTokens.remove(i);
9745                }
9746            }
9747        }
9748
9749        if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
9750            for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
9751                try {
9752                    mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
9753                } catch (RemoteException e) {
9754                }
9755            }
9756            mRelayoutWhileAnimating.clear();
9757        }
9758
9759        if (wallpaperDestroyed) {
9760            defaultDisplay.pendingLayoutChanges |=
9761                    WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
9762            defaultDisplay.layoutNeeded = true;
9763        }
9764
9765        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9766            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9767            if (displayContent.pendingLayoutChanges != 0) {
9768                displayContent.layoutNeeded = true;
9769            }
9770        }
9771
9772        // Finally update all input windows now that the window changes have stabilized.
9773        mInputMonitor.updateInputWindowsLw(true /*force*/);
9774
9775        setHoldScreenLocked(mInnerFields.mHoldScreen);
9776        if (!mDisplayFrozen) {
9777            if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
9778                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(-1);
9779            } else {
9780                mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
9781                        toBrightnessOverride(mInnerFields.mScreenBrightness));
9782            }
9783            if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
9784                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(-1);
9785            } else {
9786                mPowerManagerInternal.setButtonBrightnessOverrideFromWindowManager(
9787                        toBrightnessOverride(mInnerFields.mButtonBrightness));
9788            }
9789            mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
9790                    mInnerFields.mUserActivityTimeout);
9791        }
9792
9793        if (mTurnOnScreen) {
9794            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
9795            mPowerManager.wakeUp(SystemClock.uptimeMillis());
9796            mTurnOnScreen = false;
9797        }
9798
9799        if (mInnerFields.mUpdateRotation) {
9800            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
9801            if (updateRotationUncheckedLocked(false)) {
9802                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9803            } else {
9804                mInnerFields.mUpdateRotation = false;
9805            }
9806        }
9807
9808        if (mWaitingForDrawnCallback != null ||
9809                (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
9810                        !mInnerFields.mUpdateRotation)) {
9811            checkDrawnWindowsLocked();
9812        }
9813
9814        final int N = mPendingRemove.size();
9815        if (N > 0) {
9816            if (mPendingRemoveTmp.length < N) {
9817                mPendingRemoveTmp = new WindowState[N+10];
9818            }
9819            mPendingRemove.toArray(mPendingRemoveTmp);
9820            mPendingRemove.clear();
9821            DisplayContentList displayList = new DisplayContentList();
9822            for (i = 0; i < N; i++) {
9823                WindowState w = mPendingRemoveTmp[i];
9824                removeWindowInnerLocked(w.mSession, w);
9825                final DisplayContent displayContent = w.getDisplayContent();
9826                if (displayContent != null && !displayList.contains(displayContent)) {
9827                    displayList.add(displayContent);
9828                }
9829            }
9830
9831            for (DisplayContent displayContent : displayList) {
9832                assignLayersLocked(displayContent.getWindowList());
9833                displayContent.layoutNeeded = true;
9834            }
9835        }
9836
9837        // Remove all deferred displays stacks, tasks, and activities.
9838        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
9839            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
9840        }
9841
9842        if (updateInputWindowsNeeded) {
9843            mInputMonitor.updateInputWindowsLw(false /*force*/);
9844        }
9845        setFocusedStackFrame();
9846
9847        // Check to see if we are now in a state where the screen should
9848        // be enabled, because the window obscured flags have changed.
9849        enableScreenIfNeededLocked();
9850
9851        scheduleAnimationLocked();
9852
9853        if (DEBUG_WINDOW_TRACE) {
9854            Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating="
9855                    + mAnimator.mAnimating);
9856        }
9857    }
9858
9859    private int toBrightnessOverride(float value) {
9860        return (int)(value * PowerManager.BRIGHTNESS_ON);
9861    }
9862
9863    void checkDrawnWindowsLocked() {
9864        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
9865            return;
9866        }
9867        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
9868            WindowState win = mWaitingForDrawn.get(j);
9869            if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
9870                    ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
9871                    " mHasSurface=" + win.mHasSurface +
9872                    " drawState=" + win.mWinAnimator.mDrawState);
9873            if (win.mRemoved || !win.mHasSurface) {
9874                // Window has been removed; no draw will now happen, so stop waiting.
9875                if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
9876                mWaitingForDrawn.remove(win);
9877            } else if (win.hasDrawnLw()) {
9878                // Window is now drawn (and shown).
9879                if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
9880                mWaitingForDrawn.remove(win);
9881            }
9882        }
9883        if (mWaitingForDrawn.isEmpty()) {
9884            if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
9885            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
9886            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
9887        }
9888    }
9889
9890    void setHoldScreenLocked(final Session newHoldScreen) {
9891        final boolean hold = newHoldScreen != null;
9892
9893        if (hold && mHoldingScreenOn != newHoldScreen) {
9894            mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
9895        }
9896        mHoldingScreenOn = newHoldScreen;
9897
9898        final boolean state = mHoldingScreenWakeLock.isHeld();
9899        if (hold != state) {
9900            if (hold) {
9901                mHoldingScreenWakeLock.acquire();
9902                mPolicy.keepScreenOnStartedLw();
9903            } else {
9904                mPolicy.keepScreenOnStoppedLw();
9905                mHoldingScreenWakeLock.release();
9906            }
9907        }
9908    }
9909
9910    void requestTraversal() {
9911        synchronized (mWindowMap) {
9912            requestTraversalLocked();
9913        }
9914    }
9915
9916    void requestTraversalLocked() {
9917        if (!mTraversalScheduled) {
9918            mTraversalScheduled = true;
9919            mH.sendEmptyMessage(H.DO_TRAVERSAL);
9920        }
9921    }
9922
9923    /** Note that Locked in this case is on mLayoutToAnim */
9924    void scheduleAnimationLocked() {
9925        if (!mAnimationScheduled) {
9926            mAnimationScheduled = true;
9927            mChoreographer.postCallback(
9928                    Choreographer.CALLBACK_ANIMATION, mAnimator.mAnimationRunnable, null);
9929        }
9930    }
9931
9932    private boolean needsLayout() {
9933        final int numDisplays = mDisplayContents.size();
9934        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
9935            final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
9936            if (displayContent.layoutNeeded) {
9937                return true;
9938            }
9939        }
9940        return false;
9941    }
9942
9943    boolean copyAnimToLayoutParamsLocked() {
9944        boolean doRequest = false;
9945
9946        final int bulkUpdateParams = mAnimator.mBulkUpdateParams;
9947        if ((bulkUpdateParams & LayoutFields.SET_UPDATE_ROTATION) != 0) {
9948            mInnerFields.mUpdateRotation = true;
9949            doRequest = true;
9950        }
9951        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
9952            mInnerFields.mWallpaperMayChange = true;
9953            doRequest = true;
9954        }
9955        if ((bulkUpdateParams & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
9956            mInnerFields.mWallpaperForceHidingChanged = true;
9957            doRequest = true;
9958        }
9959        if ((bulkUpdateParams & LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE) == 0) {
9960            mInnerFields.mOrientationChangeComplete = false;
9961        } else {
9962            mInnerFields.mOrientationChangeComplete = true;
9963            mInnerFields.mLastWindowFreezeSource = mAnimator.mLastWindowFreezeSource;
9964            if (mWindowsFreezingScreen) {
9965                doRequest = true;
9966            }
9967        }
9968        if ((bulkUpdateParams & LayoutFields.SET_TURN_ON_SCREEN) != 0) {
9969            mTurnOnScreen = true;
9970        }
9971        if ((bulkUpdateParams & LayoutFields.SET_WALLPAPER_ACTION_PENDING) != 0) {
9972            mInnerFields.mWallpaperActionPending = true;
9973        }
9974
9975        return doRequest;
9976    }
9977
9978    /** If a window that has an animation specifying a colored background and the current wallpaper
9979     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
9980     * suddenly disappear. */
9981    int adjustAnimationBackground(WindowStateAnimator winAnimator) {
9982        WindowList windows = winAnimator.mWin.getWindowList();
9983        for (int i = windows.size() - 1; i >= 0; --i) {
9984            WindowState testWin = windows.get(i);
9985            if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
9986                return testWin.mWinAnimator.mAnimLayer;
9987            }
9988        }
9989        return winAnimator.mAnimLayer;
9990    }
9991
9992    boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
9993                                           boolean secure) {
9994        final SurfaceControl surface = winAnimator.mSurfaceControl;
9995        boolean leakedSurface = false;
9996        boolean killedApps = false;
9997
9998        EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
9999                winAnimator.mSession.mPid, operation);
10000
10001        if (mForceRemoves == null) {
10002            mForceRemoves = new ArrayList<WindowState>();
10003        }
10004
10005        long callingIdentity = Binder.clearCallingIdentity();
10006        try {
10007            // There was some problem...   first, do a sanity check of the
10008            // window list to make sure we haven't left any dangling surfaces
10009            // around.
10010
10011            Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
10012            final int numDisplays = mDisplayContents.size();
10013            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10014                final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10015                final int numWindows = windows.size();
10016                for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10017                    final WindowState ws = windows.get(winNdx);
10018                    WindowStateAnimator wsa = ws.mWinAnimator;
10019                    if (wsa.mSurfaceControl != null) {
10020                        if (!mSessions.contains(wsa.mSession)) {
10021                            Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10022                                    + ws + " surface=" + wsa.mSurfaceControl
10023                                    + " token=" + ws.mToken
10024                                    + " pid=" + ws.mSession.mPid
10025                                    + " uid=" + ws.mSession.mUid);
10026                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10027                            wsa.mSurfaceControl.destroy();
10028                            wsa.mSurfaceShown = false;
10029                            wsa.mSurfaceControl = null;
10030                            ws.mHasSurface = false;
10031                            mForceRemoves.add(ws);
10032                            leakedSurface = true;
10033                        } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
10034                            Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
10035                                    + ws + " surface=" + wsa.mSurfaceControl
10036                                    + " token=" + ws.mAppToken);
10037                            if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
10038                            wsa.mSurfaceControl.destroy();
10039                            wsa.mSurfaceShown = false;
10040                            wsa.mSurfaceControl = null;
10041                            ws.mHasSurface = false;
10042                            leakedSurface = true;
10043                        }
10044                    }
10045                }
10046            }
10047
10048            if (!leakedSurface) {
10049                Slog.w(TAG, "No leaked surfaces; killing applicatons!");
10050                SparseIntArray pidCandidates = new SparseIntArray();
10051                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10052                    final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
10053                    final int numWindows = windows.size();
10054                    for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
10055                        final WindowState ws = windows.get(winNdx);
10056                        if (mForceRemoves.contains(ws)) {
10057                            continue;
10058                        }
10059                        WindowStateAnimator wsa = ws.mWinAnimator;
10060                        if (wsa.mSurfaceControl != null) {
10061                            pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
10062                        }
10063                    }
10064                    if (pidCandidates.size() > 0) {
10065                        int[] pids = new int[pidCandidates.size()];
10066                        for (int i=0; i<pids.length; i++) {
10067                            pids[i] = pidCandidates.keyAt(i);
10068                        }
10069                        try {
10070                            if (mActivityManager.killPids(pids, "Free memory", secure)) {
10071                                killedApps = true;
10072                            }
10073                        } catch (RemoteException e) {
10074                        }
10075                    }
10076                }
10077            }
10078
10079            if (leakedSurface || killedApps) {
10080                // We managed to reclaim some memory, so get rid of the trouble
10081                // surface and ask the app to request another one.
10082                Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10083                if (surface != null) {
10084                    if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
10085                            "RECOVER DESTROY", null);
10086                    surface.destroy();
10087                    winAnimator.mSurfaceShown = false;
10088                    winAnimator.mSurfaceControl = null;
10089                    winAnimator.mWin.mHasSurface = false;
10090                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
10091                }
10092
10093                try {
10094                    winAnimator.mWin.mClient.dispatchGetNewSurface();
10095                } catch (RemoteException e) {
10096                }
10097            }
10098        } finally {
10099            Binder.restoreCallingIdentity(callingIdentity);
10100        }
10101
10102        return leakedSurface || killedApps;
10103    }
10104
10105    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
10106        WindowState newFocus = computeFocusedWindowLocked();
10107        if (mCurrentFocus != newFocus) {
10108            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
10109            // This check makes sure that we don't already have the focus
10110            // change message pending.
10111            mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10112            mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10113            // TODO(multidisplay): Focused windows on default display only.
10114            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10115            final boolean imWindowChanged = moveInputMethodWindowsIfNeededLocked(
10116                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
10117                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
10118            if (imWindowChanged) {
10119                displayContent.layoutNeeded = true;
10120                newFocus = computeFocusedWindowLocked();
10121            }
10122
10123            if (DEBUG_FOCUS_LIGHT || localLOGV) Slog.v(TAG, "Changing focus from " +
10124                    mCurrentFocus + " to " + newFocus + " Callers=" + Debug.getCallers(4));
10125            final WindowState oldFocus = mCurrentFocus;
10126            mCurrentFocus = newFocus;
10127            mLosingFocus.remove(newFocus);
10128
10129            // TODO(multidisplay): Accessibilty supported only of default desiplay.
10130            if (mAccessibilityController != null
10131                    && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
10132                mAccessibilityController.onWindowFocusChangedLocked();
10133            }
10134
10135            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
10136
10137            if (imWindowChanged && oldFocus != mInputMethodWindow) {
10138                // Focus of the input method window changed. Perform layout if needed.
10139                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10140                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10141                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
10142                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10143                    // Client will do the layout, but we need to assign layers
10144                    // for handleNewWindowLocked() below.
10145                    assignLayersLocked(displayContent.getWindowList());
10146                }
10147            }
10148
10149            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
10150                // The change in focus caused us to need to do a layout.  Okay.
10151                displayContent.layoutNeeded = true;
10152                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10153                    performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
10154                }
10155            }
10156
10157            if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10158                // If we defer assigning layers, then the caller is responsible for
10159                // doing this part.
10160                mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
10161            }
10162
10163            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
10164            return true;
10165        }
10166        return false;
10167    }
10168
10169    private WindowState computeFocusedWindowLocked() {
10170        if (mAnimator.mUniverseBackground != null
10171                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
10172            return mAnimator.mUniverseBackground.mWin;
10173        }
10174
10175        final int displayCount = mDisplayContents.size();
10176        for (int i = 0; i < displayCount; i++) {
10177            final DisplayContent displayContent = mDisplayContents.valueAt(i);
10178            WindowState win = findFocusedWindowLocked(displayContent);
10179            if (win != null) {
10180                return win;
10181            }
10182        }
10183        return null;
10184    }
10185
10186    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
10187        final WindowList windows = displayContent.getWindowList();
10188        for (int i = windows.size() - 1; i >= 0; i--) {
10189            final WindowState win = windows.get(i);
10190
10191            if (localLOGV || DEBUG_FOCUS) Slog.v(
10192                TAG, "Looking for focus: " + i
10193                + " = " + win
10194                + ", flags=" + win.mAttrs.flags
10195                + ", canReceive=" + win.canReceiveKeys());
10196
10197            AppWindowToken wtoken = win.mAppToken;
10198
10199            // If this window's application has been removed, just skip it.
10200            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
10201                if (DEBUG_FOCUS) Slog.v(TAG, "Skipping " + wtoken + " because "
10202                        + (wtoken.removed ? "removed" : "sendingToBottom"));
10203                continue;
10204            }
10205
10206            if (!win.canReceiveKeys()) {
10207                continue;
10208            }
10209
10210            // Descend through all of the app tokens and find the first that either matches
10211            // win.mAppToken (return win) or mFocusedApp (return null).
10212            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
10213                    mFocusedApp != null) {
10214                ArrayList<Task> tasks = displayContent.getTasks();
10215                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
10216                    AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
10217                    int tokenNdx = tokens.size() - 1;
10218                    for ( ; tokenNdx >= 0; --tokenNdx) {
10219                        final AppWindowToken token = tokens.get(tokenNdx);
10220                        if (wtoken == token) {
10221                            break;
10222                        }
10223                        if (mFocusedApp == token) {
10224                            // Whoops, we are below the focused app...  no focus for you!
10225                            if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
10226                                    "findFocusedWindow: Reached focused app=" + mFocusedApp);
10227                            return null;
10228                        }
10229                    }
10230                    if (tokenNdx >= 0) {
10231                        // Early exit from loop, must have found the matching token.
10232                        break;
10233                    }
10234                }
10235            }
10236
10237            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: Found new focus @ " + i +
10238                        " = " + win);
10239            return win;
10240        }
10241
10242        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "findFocusedWindow: No focusable windows.");
10243        return null;
10244    }
10245
10246    private void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
10247        if (mDisplayFrozen) {
10248            return;
10249        }
10250
10251        if (!mDisplayReady || !mPolicy.isScreenOnFully()) {
10252            // No need to freeze the screen before the system is ready or if
10253            // the screen is off.
10254            return;
10255        }
10256
10257        mScreenFrozenLock.acquire();
10258
10259        mDisplayFrozen = true;
10260        mDisplayFreezeTime = SystemClock.elapsedRealtime();
10261        mLastFinishedFreezeSource = null;
10262
10263        mInputMonitor.freezeInputDispatchingLw();
10264
10265        // Clear the last input window -- that is just used for
10266        // clean transitions between IMEs, and if we are freezing
10267        // the screen then the whole world is changing behind the scenes.
10268        mPolicy.setLastInputMethodWindowLw(null, null);
10269
10270        if (mAppTransition.isTransitionSet()) {
10271            mAppTransition.freeze();
10272        }
10273
10274        if (PROFILE_ORIENTATION) {
10275            File file = new File("/data/system/frozen");
10276            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10277        }
10278
10279        if (CUSTOM_SCREEN_ROTATION) {
10280            mExitAnimId = exitAnim;
10281            mEnterAnimId = enterAnim;
10282            final DisplayContent displayContent = getDefaultDisplayContentLocked();
10283            final int displayId = displayContent.getDisplayId();
10284            ScreenRotationAnimation screenRotationAnimation =
10285                    mAnimator.getScreenRotationAnimationLocked(displayId);
10286            if (screenRotationAnimation != null) {
10287                screenRotationAnimation.kill();
10288            }
10289
10290            // Check whether the current screen contains any secure content.
10291            boolean isSecure = false;
10292            final WindowList windows = getDefaultWindowListLocked();
10293            final int N = windows.size();
10294            for (int i = 0; i < N; i++) {
10295                WindowState ws = windows.get(i);
10296                if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
10297                    isSecure = true;
10298                    break;
10299                }
10300            }
10301
10302            // TODO(multidisplay): rotation on main screen only.
10303            displayContent.updateDisplayInfo();
10304            screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
10305                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure);
10306            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10307        }
10308    }
10309
10310    private void stopFreezingDisplayLocked() {
10311        if (!mDisplayFrozen) {
10312            return;
10313        }
10314
10315        if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
10316                || mClientFreezingScreen) {
10317            if (DEBUG_ORIENTATION) Slog.d(TAG,
10318                "stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
10319                + ", mAppsFreezingScreen=" + mAppsFreezingScreen
10320                + ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
10321                + ", mClientFreezingScreen=" + mClientFreezingScreen);
10322            return;
10323        }
10324
10325        mDisplayFrozen = false;
10326        mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
10327        StringBuilder sb = new StringBuilder(128);
10328        sb.append("Screen frozen for ");
10329        TimeUtils.formatDuration(mLastDisplayFreezeDuration, sb);
10330        if (mLastFinishedFreezeSource != null) {
10331            sb.append(" due to ");
10332            sb.append(mLastFinishedFreezeSource);
10333        }
10334        Slog.i(TAG, sb.toString());
10335        mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10336        mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
10337        if (PROFILE_ORIENTATION) {
10338            Debug.stopMethodTracing();
10339        }
10340
10341        boolean updateRotation = false;
10342
10343        final DisplayContent displayContent = getDefaultDisplayContentLocked();
10344        final int displayId = displayContent.getDisplayId();
10345        ScreenRotationAnimation screenRotationAnimation =
10346                mAnimator.getScreenRotationAnimationLocked(displayId);
10347        if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
10348                && screenRotationAnimation.hasScreenshot()) {
10349            if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
10350            // TODO(multidisplay): rotation on main screen only.
10351            DisplayInfo displayInfo = displayContent.getDisplayInfo();
10352            // Get rotation animation again, with new top window
10353            boolean isDimming = displayContent.isDimming();
10354            if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) {
10355                mExitAnimId = mEnterAnimId = 0;
10356            }
10357            if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
10358                    getTransitionAnimationScaleLocked(), displayInfo.logicalWidth,
10359                        displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) {
10360                scheduleAnimationLocked();
10361            } else {
10362                screenRotationAnimation.kill();
10363                screenRotationAnimation = null;
10364                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10365                updateRotation = true;
10366            }
10367        } else {
10368            if (screenRotationAnimation != null) {
10369                screenRotationAnimation.kill();
10370                screenRotationAnimation = null;
10371                mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
10372            }
10373            updateRotation = true;
10374        }
10375
10376        mInputMonitor.thawInputDispatchingLw();
10377
10378        boolean configChanged;
10379
10380        // While the display is frozen we don't re-compute the orientation
10381        // to avoid inconsistent states.  However, something interesting
10382        // could have actually changed during that time so re-evaluate it
10383        // now to catch that.
10384        configChanged = updateOrientationFromAppTokensLocked(false);
10385
10386        // A little kludge: a lot could have happened while the
10387        // display was frozen, so now that we are coming back we
10388        // do a gc so that any remote references the system
10389        // processes holds on others can be released if they are
10390        // no longer needed.
10391        mH.removeMessages(H.FORCE_GC);
10392        mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000);
10393
10394        mScreenFrozenLock.release();
10395
10396        if (updateRotation) {
10397            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
10398            configChanged |= updateRotationUncheckedLocked(false);
10399        }
10400
10401        if (configChanged) {
10402            mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10403        }
10404    }
10405
10406    static int getPropertyInt(String[] tokens, int index, int defUnits, int defDps,
10407            DisplayMetrics dm) {
10408        if (index < tokens.length) {
10409            String str = tokens[index];
10410            if (str != null && str.length() > 0) {
10411                try {
10412                    int val = Integer.parseInt(str);
10413                    return val;
10414                } catch (Exception e) {
10415                }
10416            }
10417        }
10418        if (defUnits == TypedValue.COMPLEX_UNIT_PX) {
10419            return defDps;
10420        }
10421        int val = (int)TypedValue.applyDimension(defUnits, defDps, dm);
10422        return val;
10423    }
10424
10425    void createWatermarkInTransaction() {
10426        if (mWatermark != null) {
10427            return;
10428        }
10429
10430        File file = new File("/system/etc/setup.conf");
10431        FileInputStream in = null;
10432        DataInputStream ind = null;
10433        try {
10434            in = new FileInputStream(file);
10435            ind = new DataInputStream(in);
10436            String line = ind.readLine();
10437            if (line != null) {
10438                String[] toks = line.split("%");
10439                if (toks != null && toks.length > 0) {
10440                    mWatermark = new Watermark(getDefaultDisplayContentLocked().getDisplay(),
10441                            mRealDisplayMetrics, mFxSession, toks);
10442                }
10443            }
10444        } catch (FileNotFoundException e) {
10445        } catch (IOException e) {
10446        } finally {
10447            if (ind != null) {
10448                try {
10449                    ind.close();
10450                } catch (IOException e) {
10451                }
10452            } else if (in != null) {
10453                try {
10454                    in.close();
10455                } catch (IOException e) {
10456                }
10457            }
10458        }
10459    }
10460
10461    @Override
10462    public void statusBarVisibilityChanged(int visibility) {
10463        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
10464                != PackageManager.PERMISSION_GRANTED) {
10465            throw new SecurityException("Caller does not hold permission "
10466                    + android.Manifest.permission.STATUS_BAR);
10467        }
10468
10469        synchronized (mWindowMap) {
10470            mLastStatusBarVisibility = visibility;
10471            visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
10472            updateStatusBarVisibilityLocked(visibility);
10473        }
10474    }
10475
10476    // TOOD(multidisplay): StatusBar on multiple screens?
10477    void updateStatusBarVisibilityLocked(int visibility) {
10478        mInputManager.setSystemUiVisibility(visibility);
10479        final WindowList windows = getDefaultWindowListLocked();
10480        final int N = windows.size();
10481        for (int i = 0; i < N; i++) {
10482            WindowState ws = windows.get(i);
10483            try {
10484                int curValue = ws.mSystemUiVisibility;
10485                int diff = curValue ^ visibility;
10486                // We are only interested in differences of one of the
10487                // clearable flags...
10488                diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
10489                // ...if it has actually been cleared.
10490                diff &= ~visibility;
10491                int newValue = (curValue&~diff) | (visibility&diff);
10492                if (newValue != curValue) {
10493                    ws.mSeq++;
10494                    ws.mSystemUiVisibility = newValue;
10495                }
10496                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
10497                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
10498                            visibility, newValue, diff);
10499                }
10500            } catch (RemoteException e) {
10501                // so sorry
10502            }
10503        }
10504    }
10505
10506    @Override
10507    public void reevaluateStatusBarVisibility() {
10508        synchronized (mWindowMap) {
10509            int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
10510            updateStatusBarVisibilityLocked(visibility);
10511            performLayoutAndPlaceSurfacesLocked();
10512        }
10513    }
10514
10515    @Override
10516    public FakeWindow addFakeWindow(Looper looper,
10517            InputEventReceiver.Factory inputEventReceiverFactory,
10518            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
10519            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
10520        synchronized (mWindowMap) {
10521            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
10522                    name, windowType,
10523                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
10524                    hasFocus, touchFullscreen);
10525            int i=0;
10526            while (i<mFakeWindows.size()) {
10527                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
10528                    break;
10529                }
10530            }
10531            mFakeWindows.add(i, fw);
10532            mInputMonitor.updateInputWindowsLw(true);
10533            return fw;
10534        }
10535    }
10536
10537    boolean removeFakeWindowLocked(FakeWindow window) {
10538        synchronized (mWindowMap) {
10539            if (mFakeWindows.remove(window)) {
10540                mInputMonitor.updateInputWindowsLw(true);
10541                return true;
10542            }
10543            return false;
10544        }
10545    }
10546
10547    // It is assumed that this method is called only by InputMethodManagerService.
10548    public void saveLastInputMethodWindowForTransition() {
10549        synchronized (mWindowMap) {
10550            // TODO(multidisplay): Pass in the displayID.
10551            DisplayContent displayContent = getDefaultDisplayContentLocked();
10552            if (mInputMethodWindow != null) {
10553                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
10554            }
10555        }
10556    }
10557
10558    public int getInputMethodWindowVisibleHeight() {
10559        synchronized (mWindowMap) {
10560            return mPolicy.getInputMethodWindowVisibleHeightLw();
10561        }
10562    }
10563
10564    @Override
10565    public boolean hasNavigationBar() {
10566        return mPolicy.hasNavigationBar();
10567    }
10568
10569    @Override
10570    public void lockNow(Bundle options) {
10571        mPolicy.lockNow(options);
10572    }
10573
10574    public void showRecentApps() {
10575        mPolicy.showRecentApps();
10576    }
10577
10578    @Override
10579    public boolean isSafeModeEnabled() {
10580        return mSafeMode;
10581    }
10582
10583    @Override
10584    public boolean clearWindowContentFrameStats(IBinder token) {
10585        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10586                "clearWindowContentFrameStats()")) {
10587            throw new SecurityException("Requires FRAME_STATS permission");
10588        }
10589        synchronized (mWindowMap) {
10590            WindowState windowState = mWindowMap.get(token);
10591            if (windowState == null) {
10592                return false;
10593            }
10594            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10595            if (surfaceControl == null) {
10596                return false;
10597            }
10598            return surfaceControl.clearContentFrameStats();
10599        }
10600    }
10601
10602    @Override
10603    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
10604        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
10605                "getWindowContentFrameStats()")) {
10606            throw new SecurityException("Requires FRAME_STATS permission");
10607        }
10608        synchronized (mWindowMap) {
10609            WindowState windowState = mWindowMap.get(token);
10610            if (windowState == null) {
10611                return null;
10612            }
10613            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
10614            if (surfaceControl == null) {
10615                return null;
10616            }
10617            if (mTempWindowRenderStats == null) {
10618                mTempWindowRenderStats = new WindowContentFrameStats();
10619            }
10620            WindowContentFrameStats stats = mTempWindowRenderStats;
10621            if (!surfaceControl.getContentFrameStats(stats)) {
10622                return null;
10623            }
10624            return stats;
10625        }
10626    }
10627
10628    void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10629        pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
10630        mPolicy.dump("    ", pw, args);
10631    }
10632
10633    void dumpAnimatorLocked(PrintWriter pw, String[] args, boolean dumpAll) {
10634        pw.println("WINDOW MANAGER ANIMATOR STATE (dumpsys window animator)");
10635        mAnimator.dumpLocked(pw, "    ", dumpAll);
10636    }
10637
10638    void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
10639        pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
10640        if (mTokenMap.size() > 0) {
10641            pw.println("  All tokens:");
10642            Iterator<WindowToken> it = mTokenMap.values().iterator();
10643            while (it.hasNext()) {
10644                WindowToken token = it.next();
10645                pw.print("  "); pw.print(token);
10646                if (dumpAll) {
10647                    pw.println(':');
10648                    token.dump(pw, "    ");
10649                } else {
10650                    pw.println();
10651                }
10652            }
10653        }
10654        if (mWallpaperTokens.size() > 0) {
10655            pw.println();
10656            pw.println("  Wallpaper tokens:");
10657            for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10658                WindowToken token = mWallpaperTokens.get(i);
10659                pw.print("  Wallpaper #"); pw.print(i);
10660                        pw.print(' '); pw.print(token);
10661                if (dumpAll) {
10662                    pw.println(':');
10663                    token.dump(pw, "    ");
10664                } else {
10665                    pw.println();
10666                }
10667            }
10668        }
10669        if (mFinishedStarting.size() > 0) {
10670            pw.println();
10671            pw.println("  Finishing start of application tokens:");
10672            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10673                WindowToken token = mFinishedStarting.get(i);
10674                pw.print("  Finished Starting #"); pw.print(i);
10675                        pw.print(' '); pw.print(token);
10676                if (dumpAll) {
10677                    pw.println(':');
10678                    token.dump(pw, "    ");
10679                } else {
10680                    pw.println();
10681                }
10682            }
10683        }
10684        if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
10685            pw.println();
10686            if (mOpeningApps.size() > 0) {
10687                pw.print("  mOpeningApps="); pw.println(mOpeningApps);
10688            }
10689            if (mClosingApps.size() > 0) {
10690                pw.print("  mClosingApps="); pw.println(mClosingApps);
10691            }
10692        }
10693    }
10694
10695    void dumpSessionsLocked(PrintWriter pw, boolean dumpAll) {
10696        pw.println("WINDOW MANAGER SESSIONS (dumpsys window sessions)");
10697        for (int i=0; i<mSessions.size(); i++) {
10698            Session s = mSessions.valueAt(i);
10699            pw.print("  Session "); pw.print(s); pw.println(':');
10700            s.dump(pw, "    ");
10701        }
10702    }
10703
10704    void dumpDisplayContentsLocked(PrintWriter pw, boolean dumpAll) {
10705        pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
10706        if (mDisplayReady) {
10707            final int numDisplays = mDisplayContents.size();
10708            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10709                final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10710                displayContent.dump("  ", pw);
10711            }
10712        } else {
10713            pw.println("  NO DISPLAY");
10714        }
10715    }
10716
10717    void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
10718            ArrayList<WindowState> windows) {
10719        pw.println("WINDOW MANAGER WINDOWS (dumpsys window windows)");
10720        dumpWindowsNoHeaderLocked(pw, dumpAll, windows);
10721    }
10722
10723    void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
10724            ArrayList<WindowState> windows) {
10725        final int numDisplays = mDisplayContents.size();
10726        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10727            final WindowList windowList = mDisplayContents.valueAt(displayNdx).getWindowList();
10728            for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10729                final WindowState w = windowList.get(winNdx);
10730                if (windows == null || windows.contains(w)) {
10731                    pw.print("  Window #"); pw.print(winNdx); pw.print(' ');
10732                            pw.print(w); pw.println(":");
10733                    w.dump(pw, "    ", dumpAll || windows != null);
10734                }
10735            }
10736        }
10737        if (mInputMethodDialogs.size() > 0) {
10738            pw.println();
10739            pw.println("  Input method dialogs:");
10740            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10741                WindowState w = mInputMethodDialogs.get(i);
10742                if (windows == null || windows.contains(w)) {
10743                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
10744                }
10745            }
10746        }
10747        if (mPendingRemove.size() > 0) {
10748            pw.println();
10749            pw.println("  Remove pending for:");
10750            for (int i=mPendingRemove.size()-1; i>=0; i--) {
10751                WindowState w = mPendingRemove.get(i);
10752                if (windows == null || windows.contains(w)) {
10753                    pw.print("  Remove #"); pw.print(i); pw.print(' ');
10754                            pw.print(w);
10755                    if (dumpAll) {
10756                        pw.println(":");
10757                        w.dump(pw, "    ", true);
10758                    } else {
10759                        pw.println();
10760                    }
10761                }
10762            }
10763        }
10764        if (mForceRemoves != null && mForceRemoves.size() > 0) {
10765            pw.println();
10766            pw.println("  Windows force removing:");
10767            for (int i=mForceRemoves.size()-1; i>=0; i--) {
10768                WindowState w = mForceRemoves.get(i);
10769                pw.print("  Removing #"); pw.print(i); pw.print(' ');
10770                        pw.print(w);
10771                if (dumpAll) {
10772                    pw.println(":");
10773                    w.dump(pw, "    ", true);
10774                } else {
10775                    pw.println();
10776                }
10777            }
10778        }
10779        if (mDestroySurface.size() > 0) {
10780            pw.println();
10781            pw.println("  Windows waiting to destroy their surface:");
10782            for (int i=mDestroySurface.size()-1; i>=0; i--) {
10783                WindowState w = mDestroySurface.get(i);
10784                if (windows == null || windows.contains(w)) {
10785                    pw.print("  Destroy #"); pw.print(i); pw.print(' ');
10786                            pw.print(w);
10787                    if (dumpAll) {
10788                        pw.println(":");
10789                        w.dump(pw, "    ", true);
10790                    } else {
10791                        pw.println();
10792                    }
10793                }
10794            }
10795        }
10796        if (mLosingFocus.size() > 0) {
10797            pw.println();
10798            pw.println("  Windows losing focus:");
10799            for (int i=mLosingFocus.size()-1; i>=0; i--) {
10800                WindowState w = mLosingFocus.get(i);
10801                if (windows == null || windows.contains(w)) {
10802                    pw.print("  Losing #"); pw.print(i); pw.print(' ');
10803                            pw.print(w);
10804                    if (dumpAll) {
10805                        pw.println(":");
10806                        w.dump(pw, "    ", true);
10807                    } else {
10808                        pw.println();
10809                    }
10810                }
10811            }
10812        }
10813        if (mResizingWindows.size() > 0) {
10814            pw.println();
10815            pw.println("  Windows waiting to resize:");
10816            for (int i=mResizingWindows.size()-1; i>=0; i--) {
10817                WindowState w = mResizingWindows.get(i);
10818                if (windows == null || windows.contains(w)) {
10819                    pw.print("  Resizing #"); pw.print(i); pw.print(' ');
10820                            pw.print(w);
10821                    if (dumpAll) {
10822                        pw.println(":");
10823                        w.dump(pw, "    ", true);
10824                    } else {
10825                        pw.println();
10826                    }
10827                }
10828            }
10829        }
10830        if (mWaitingForDrawn.size() > 0) {
10831            pw.println();
10832            pw.println("  Clients waiting for these windows to be drawn:");
10833            for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
10834                WindowState win = mWaitingForDrawn.get(i);
10835                pw.print("  Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
10836            }
10837        }
10838        pw.println();
10839        pw.print("  mCurConfiguration="); pw.println(this.mCurConfiguration);
10840        pw.print("  mCurrentFocus="); pw.println(mCurrentFocus);
10841        if (mLastFocus != mCurrentFocus) {
10842            pw.print("  mLastFocus="); pw.println(mLastFocus);
10843        }
10844        pw.print("  mFocusedApp="); pw.println(mFocusedApp);
10845        if (mInputMethodTarget != null) {
10846            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
10847        }
10848        pw.print("  mInTouchMode="); pw.print(mInTouchMode);
10849                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
10850        pw.print("  mLastDisplayFreezeDuration=");
10851                TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
10852                if ( mLastFinishedFreezeSource != null) {
10853                    pw.print(" due to ");
10854                    pw.print(mLastFinishedFreezeSource);
10855                }
10856                pw.println();
10857        if (dumpAll) {
10858            pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
10859                    pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
10860            if (mLastStatusBarVisibility != 0) {
10861                pw.print("  mLastStatusBarVisibility=0x");
10862                        pw.println(Integer.toHexString(mLastStatusBarVisibility));
10863            }
10864            if (mInputMethodWindow != null) {
10865                pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
10866            }
10867            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
10868            if (mLowerWallpaperTarget != null || mUpperWallpaperTarget != null) {
10869                pw.print("  mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10870                pw.print("  mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10871            }
10872            pw.print("  mLastWallpaperX="); pw.print(mLastWallpaperX);
10873                    pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
10874            if (mInputMethodAnimLayerAdjustment != 0 ||
10875                    mWallpaperAnimLayerAdjustment != 0) {
10876                pw.print("  mInputMethodAnimLayerAdjustment=");
10877                        pw.print(mInputMethodAnimLayerAdjustment);
10878                        pw.print("  mWallpaperAnimLayerAdjustment=");
10879                        pw.println(mWallpaperAnimLayerAdjustment);
10880            }
10881            pw.print("  mSystemBooted="); pw.print(mSystemBooted);
10882                    pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10883            if (needsLayout()) {
10884                pw.print("  layoutNeeded on displays=");
10885                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10886                    final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
10887                    if (displayContent.layoutNeeded) {
10888                        pw.print(displayContent.getDisplayId());
10889                    }
10890                }
10891                pw.println();
10892            }
10893            pw.print("  mTransactionSequence="); pw.println(mTransactionSequence);
10894            pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
10895                    pw.print(" windows="); pw.print(mWindowsFreezingScreen);
10896                    pw.print(" client="); pw.print(mClientFreezingScreen);
10897                    pw.print(" apps="); pw.print(mAppsFreezingScreen);
10898                    pw.print(" waitingForConfig="); pw.println(mWaitingForConfig);
10899            pw.print("  mRotation="); pw.print(mRotation);
10900                    pw.print(" mAltOrientation="); pw.println(mAltOrientation);
10901            pw.print("  mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
10902                    pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
10903            pw.print("  mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
10904            pw.print("  Animation settings: disabled="); pw.print(mAnimationsDisabled);
10905                    pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
10906                    pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
10907                    pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
10908            pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
10909            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10910                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10911            pw.println("  mLayoutToAnim:");
10912            mAppTransition.dump(pw);
10913        }
10914    }
10915
10916    boolean dumpWindows(PrintWriter pw, String name, String[] args,
10917            int opti, boolean dumpAll) {
10918        WindowList windows = new WindowList();
10919        if ("visible".equals(name)) {
10920            synchronized(mWindowMap) {
10921                final int numDisplays = mDisplayContents.size();
10922                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10923                    final WindowList windowList =
10924                            mDisplayContents.valueAt(displayNdx).getWindowList();
10925                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10926                        final WindowState w = windowList.get(winNdx);
10927                        if (w.mWinAnimator.mSurfaceShown) {
10928                            windows.add(w);
10929                        }
10930                    }
10931                }
10932            }
10933        } else {
10934            int objectId = 0;
10935            // See if this is an object ID.
10936            try {
10937                objectId = Integer.parseInt(name, 16);
10938                name = null;
10939            } catch (RuntimeException e) {
10940            }
10941            synchronized(mWindowMap) {
10942                final int numDisplays = mDisplayContents.size();
10943                for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
10944                    final WindowList windowList =
10945                            mDisplayContents.valueAt(displayNdx).getWindowList();
10946                    for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) {
10947                        final WindowState w = windowList.get(winNdx);
10948                        if (name != null) {
10949                            if (w.mAttrs.getTitle().toString().contains(name)) {
10950                                windows.add(w);
10951                            }
10952                        } else if (System.identityHashCode(w) == objectId) {
10953                            windows.add(w);
10954                        }
10955                    }
10956                }
10957            }
10958        }
10959
10960        if (windows.size() <= 0) {
10961            return false;
10962        }
10963
10964        synchronized(mWindowMap) {
10965            dumpWindowsLocked(pw, dumpAll, windows);
10966        }
10967        return true;
10968    }
10969
10970    void dumpLastANRLocked(PrintWriter pw) {
10971        pw.println("WINDOW MANAGER LAST ANR (dumpsys window lastanr)");
10972        if (mLastANRState == null) {
10973            pw.println("  <no ANR has occurred since boot>");
10974        } else {
10975            pw.println(mLastANRState);
10976        }
10977    }
10978
10979    /**
10980     * Saves information about the state of the window manager at
10981     * the time an ANR occurred before anything else in the system changes
10982     * in response.
10983     *
10984     * @param appWindowToken The application that ANR'd, may be null.
10985     * @param windowState The window that ANR'd, may be null.
10986     * @param reason The reason for the ANR, may be null.
10987     */
10988    public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
10989            String reason) {
10990        StringWriter sw = new StringWriter();
10991        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
10992        pw.println("  ANR time: " + DateFormat.getInstance().format(new Date()));
10993        if (appWindowToken != null) {
10994            pw.println("  Application at fault: " + appWindowToken.stringName);
10995        }
10996        if (windowState != null) {
10997            pw.println("  Window at fault: " + windowState.mAttrs.getTitle());
10998        }
10999        if (reason != null) {
11000            pw.println("  Reason: " + reason);
11001        }
11002        pw.println();
11003        dumpWindowsNoHeaderLocked(pw, true, null);
11004        pw.close();
11005        mLastANRState = sw.toString();
11006    }
11007
11008    @Override
11009    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11010        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11011                != PackageManager.PERMISSION_GRANTED) {
11012            pw.println("Permission Denial: can't dump WindowManager from from pid="
11013                    + Binder.getCallingPid()
11014                    + ", uid=" + Binder.getCallingUid());
11015            return;
11016        }
11017
11018        boolean dumpAll = false;
11019
11020        int opti = 0;
11021        while (opti < args.length) {
11022            String opt = args[opti];
11023            if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
11024                break;
11025            }
11026            opti++;
11027            if ("-a".equals(opt)) {
11028                dumpAll = true;
11029            } else if ("-h".equals(opt)) {
11030                pw.println("Window manager dump options:");
11031                pw.println("  [-a] [-h] [cmd] ...");
11032                pw.println("  cmd may be one of:");
11033                pw.println("    l[astanr]: last ANR information");
11034                pw.println("    p[policy]: policy state");
11035                pw.println("    a[animator]: animator state");
11036                pw.println("    s[essions]: active sessions");
11037                pw.println("    d[isplays]: active display contents");
11038                pw.println("    t[okens]: token list");
11039                pw.println("    w[indows]: window list");
11040                pw.println("  cmd may also be a NAME to dump windows.  NAME may");
11041                pw.println("    be a partial substring in a window name, a");
11042                pw.println("    Window hex object identifier, or");
11043                pw.println("    \"all\" for all windows, or");
11044                pw.println("    \"visible\" for the visible windows.");
11045                pw.println("  -a: include all available server state.");
11046                return;
11047            } else {
11048                pw.println("Unknown argument: " + opt + "; use -h for help");
11049            }
11050        }
11051
11052        // Is the caller requesting to dump a particular piece of data?
11053        if (opti < args.length) {
11054            String cmd = args[opti];
11055            opti++;
11056            if ("lastanr".equals(cmd) || "l".equals(cmd)) {
11057                synchronized(mWindowMap) {
11058                    dumpLastANRLocked(pw);
11059                }
11060                return;
11061            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
11062                synchronized(mWindowMap) {
11063                    dumpPolicyLocked(pw, args, true);
11064                }
11065                return;
11066            } else if ("animator".equals(cmd) || "a".equals(cmd)) {
11067                synchronized(mWindowMap) {
11068                    dumpAnimatorLocked(pw, args, true);
11069                }
11070                return;
11071            } else if ("sessions".equals(cmd) || "s".equals(cmd)) {
11072                synchronized(mWindowMap) {
11073                    dumpSessionsLocked(pw, true);
11074                }
11075                return;
11076            } else if ("displays".equals(cmd) || "d".equals(cmd)) {
11077                synchronized(mWindowMap) {
11078                    dumpDisplayContentsLocked(pw, true);
11079                }
11080                return;
11081            } else if ("tokens".equals(cmd) || "t".equals(cmd)) {
11082                synchronized(mWindowMap) {
11083                    dumpTokensLocked(pw, true);
11084                }
11085                return;
11086            } else if ("windows".equals(cmd) || "w".equals(cmd)) {
11087                synchronized(mWindowMap) {
11088                    dumpWindowsLocked(pw, true, null);
11089                }
11090                return;
11091            } else if ("all".equals(cmd) || "a".equals(cmd)) {
11092                synchronized(mWindowMap) {
11093                    dumpWindowsLocked(pw, true, null);
11094                }
11095                return;
11096            } else {
11097                // Dumping a single name?
11098                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
11099                    pw.println("Bad window command, or no windows match: " + cmd);
11100                    pw.println("Use -h for help.");
11101                }
11102                return;
11103            }
11104        }
11105
11106        synchronized(mWindowMap) {
11107            pw.println();
11108            if (dumpAll) {
11109                pw.println("-------------------------------------------------------------------------------");
11110            }
11111            dumpLastANRLocked(pw);
11112            pw.println();
11113            if (dumpAll) {
11114                pw.println("-------------------------------------------------------------------------------");
11115            }
11116            dumpPolicyLocked(pw, args, dumpAll);
11117            pw.println();
11118            if (dumpAll) {
11119                pw.println("-------------------------------------------------------------------------------");
11120            }
11121            dumpAnimatorLocked(pw, args, dumpAll);
11122            pw.println();
11123            if (dumpAll) {
11124                pw.println("-------------------------------------------------------------------------------");
11125            }
11126            dumpSessionsLocked(pw, dumpAll);
11127            pw.println();
11128            if (dumpAll) {
11129                pw.println("-------------------------------------------------------------------------------");
11130            }
11131            dumpDisplayContentsLocked(pw, dumpAll);
11132            pw.println();
11133            if (dumpAll) {
11134                pw.println("-------------------------------------------------------------------------------");
11135            }
11136            dumpTokensLocked(pw, dumpAll);
11137            pw.println();
11138            if (dumpAll) {
11139                pw.println("-------------------------------------------------------------------------------");
11140            }
11141            dumpWindowsLocked(pw, dumpAll, null);
11142        }
11143    }
11144
11145    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
11146    @Override
11147    public void monitor() {
11148        synchronized (mWindowMap) { }
11149    }
11150
11151    public interface OnHardKeyboardStatusChangeListener {
11152        public void onHardKeyboardStatusChange(boolean available);
11153    }
11154
11155    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
11156        if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
11157            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
11158                    Integer.toHexString(pendingLayoutChanges));
11159        }
11160    }
11161
11162    private DisplayContent newDisplayContentLocked(final Display display) {
11163        DisplayContent displayContent = new DisplayContent(display, this);
11164        final int displayId = display.getDisplayId();
11165        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
11166        mDisplayContents.put(displayId, displayContent);
11167
11168        DisplayInfo displayInfo = displayContent.getDisplayInfo();
11169        final Rect rect = new Rect();
11170        mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
11171        synchronized (displayContent.mDisplaySizeLock) {
11172            displayInfo.overscanLeft = rect.left;
11173            displayInfo.overscanTop = rect.top;
11174            displayInfo.overscanRight = rect.right;
11175            displayInfo.overscanBottom = rect.bottom;
11176            mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
11177                    displayId, displayInfo);
11178        }
11179        configureDisplayPolicyLocked(displayContent);
11180
11181        // TODO: Create an input channel for each display with touch capability.
11182        if (displayId == Display.DEFAULT_DISPLAY) {
11183            displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
11184            registerPointerEventListener(displayContent.mTapDetector);
11185        }
11186
11187        return displayContent;
11188    }
11189
11190    public void createDisplayContentLocked(final Display display) {
11191        if (display == null) {
11192            throw new IllegalArgumentException("getDisplayContent: display must not be null");
11193        }
11194        getDisplayContentLocked(display.getDisplayId());
11195    }
11196
11197    /**
11198     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
11199     * there is a Display for the displayId.
11200     * @param displayId The display the caller is interested in.
11201     * @return The DisplayContent associated with displayId or null if there is no Display for it.
11202     */
11203    public DisplayContent getDisplayContentLocked(final int displayId) {
11204        DisplayContent displayContent = mDisplayContents.get(displayId);
11205        if (displayContent == null) {
11206            final Display display = mDisplayManager.getDisplay(displayId);
11207            if (display != null) {
11208                displayContent = newDisplayContentLocked(display);
11209            }
11210        }
11211        return displayContent;
11212    }
11213
11214    // There is an inherent assumption that this will never return null.
11215    public DisplayContent getDefaultDisplayContentLocked() {
11216        return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
11217    }
11218
11219    public WindowList getDefaultWindowListLocked() {
11220        return getDefaultDisplayContentLocked().getWindowList();
11221    }
11222
11223    public DisplayInfo getDefaultDisplayInfoLocked() {
11224        return getDefaultDisplayContentLocked().getDisplayInfo();
11225    }
11226
11227    /**
11228     * Return the list of WindowStates associated on the passed display.
11229     * @param display The screen to return windows from.
11230     * @return The list of WindowStates on the screen, or null if the there is no screen.
11231     */
11232    public WindowList getWindowListLocked(final Display display) {
11233        return getWindowListLocked(display.getDisplayId());
11234    }
11235
11236    /**
11237     * Return the list of WindowStates associated on the passed display.
11238     * @param displayId The screen to return windows from.
11239     * @return The list of WindowStates on the screen, or null if the there is no screen.
11240     */
11241    public WindowList getWindowListLocked(final int displayId) {
11242        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11243        return displayContent != null ? displayContent.getWindowList() : null;
11244    }
11245
11246    public void onDisplayAdded(int displayId) {
11247        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_ADDED, displayId, 0));
11248    }
11249
11250    public void handleDisplayAdded(int displayId) {
11251        synchronized (mWindowMap) {
11252            final Display display = mDisplayManager.getDisplay(displayId);
11253            if (display != null) {
11254                createDisplayContentLocked(display);
11255                displayReady(displayId);
11256            }
11257        }
11258    }
11259
11260    public void onDisplayRemoved(int displayId) {
11261        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_REMOVED, displayId, 0));
11262    }
11263
11264    private void handleDisplayRemovedLocked(int displayId) {
11265        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11266        if (displayContent != null) {
11267            if (displayContent.isAnimating()) {
11268                displayContent.mDeferredRemoval = true;
11269                return;
11270            }
11271            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
11272            mDisplayContents.delete(displayId);
11273            displayContent.close();
11274            if (displayId == Display.DEFAULT_DISPLAY) {
11275                unregisterPointerEventListener(displayContent.mTapDetector);
11276            }
11277        }
11278        mAnimator.removeDisplayLocked(displayId);
11279    }
11280
11281    public void onDisplayChanged(int displayId) {
11282        mH.sendMessage(mH.obtainMessage(H.DO_DISPLAY_CHANGED, displayId, 0));
11283    }
11284
11285    private void handleDisplayChangedLocked(int displayId) {
11286        final DisplayContent displayContent = getDisplayContentLocked(displayId);
11287        if (displayContent != null) {
11288            displayContent.updateDisplayInfo();
11289        }
11290    }
11291
11292    @Override
11293    public Object getWindowManagerLock() {
11294        return mWindowMap;
11295    }
11296
11297    private final class LocalService extends WindowManagerInternal {
11298        @Override
11299        public void requestTraversalFromDisplayManager() {
11300            requestTraversal();
11301        }
11302
11303        @Override
11304        public void setMagnificationSpec(MagnificationSpec spec) {
11305            synchronized (mWindowMap) {
11306                if (mAccessibilityController != null) {
11307                    mAccessibilityController.setMagnificationSpecLocked(spec);
11308                } else {
11309                    throw new IllegalStateException("Magnification callbacks not set!");
11310                }
11311            }
11312            if (Binder.getCallingPid() != android.os.Process.myPid()) {
11313                spec.recycle();
11314            }
11315        }
11316
11317        @Override
11318        public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
11319            synchronized (mWindowMap) {
11320                WindowState windowState = mWindowMap.get(windowToken);
11321                if (windowState == null) {
11322                    return null;
11323                }
11324                MagnificationSpec spec = null;
11325                if (mAccessibilityController != null) {
11326                    spec = mAccessibilityController.getMagnificationSpecForWindowLocked(windowState);
11327                }
11328                if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
11329                    return null;
11330                }
11331                spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
11332                spec.scale *= windowState.mGlobalScale;
11333                return spec;
11334            }
11335        }
11336
11337        @Override
11338        public void setMagnificationCallbacks(MagnificationCallbacks callbacks) {
11339            synchronized (mWindowMap) {
11340                if (mAccessibilityController == null) {
11341                    mAccessibilityController = new AccessibilityController(
11342                            WindowManagerService.this);
11343                }
11344                mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
11345                if (!mAccessibilityController.hasCallbacksLocked()) {
11346                    mAccessibilityController = null;
11347                }
11348            }
11349        }
11350
11351        @Override
11352        public void setWindowsForAccessibilityCallback(WindowsForAccessibilityCallback callback) {
11353            synchronized (mWindowMap) {
11354                if (mAccessibilityController == null) {
11355                    mAccessibilityController = new AccessibilityController(
11356                            WindowManagerService.this);
11357                }
11358                mAccessibilityController.setWindowsForAccessibilityCallback(callback);
11359                if (!mAccessibilityController.hasCallbacksLocked()) {
11360                    mAccessibilityController = null;
11361                }
11362            }
11363        }
11364
11365        @Override
11366        public void setInputFilter(IInputFilter filter) {
11367            mInputManager.setInputFilter(filter);
11368        }
11369
11370        @Override
11371        public IBinder getFocusedWindowToken() {
11372            synchronized (mWindowMap) {
11373                WindowState windowState = getFocusedWindowLocked();
11374                if (windowState != null) {
11375                    return windowState.mClient.asBinder();
11376                }
11377                return null;
11378            }
11379        }
11380
11381        @Override
11382        public boolean isKeyguardLocked() {
11383            return WindowManagerService.this.isKeyguardLocked();
11384        }
11385
11386        @Override
11387        public void showGlobalActions() {
11388            WindowManagerService.this.showGlobalActions();
11389        }
11390
11391        @Override
11392        public void getWindowFrame(IBinder token, Rect outBounds) {
11393            synchronized (mWindowMap) {
11394                WindowState windowState = mWindowMap.get(token);
11395                if (windowState != null) {
11396                    outBounds.set(windowState.mFrame);
11397                } else {
11398                    outBounds.setEmpty();
11399                }
11400            }
11401        }
11402
11403        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
11404            synchronized (mWindowMap) {
11405                mWaitingForDrawnCallback = callback;
11406                final WindowList windows = getDefaultWindowListLocked();
11407                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
11408                    final WindowState win = windows.get(winNdx);
11409                    if (win.mHasSurface && win.mAppToken != null) {
11410                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
11411                        // Force add to mResizingWindows.
11412                        win.mLastContentInsets.set(-1, -1, -1, -1);
11413                        mWaitingForDrawn.add(win);
11414                    }
11415                }
11416                requestTraversalLocked();
11417            }
11418            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
11419            if (mWaitingForDrawn.isEmpty()) {
11420                callback.run();
11421            } else {
11422                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
11423                checkDrawnWindowsLocked();
11424            }
11425        }
11426    }
11427}
11428