import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
static final boolean DEBUG_ANIM = false;
+ static final boolean DEBUG_KEYGUARD = false;
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG_LAYERS = false;
/** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
+ /** Amount of time to allow a last ANR message to exist before freeing the memory. */
+ static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
/**
* If true, the window manager will do its own custom freezing and general
* management of the screen during rotation.
boolean mClientFreezingScreen = false;
int mAppsFreezingScreen = 0;
int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ int mLastKeyguardForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
int mLayoutSeq = 0;
SettingsObserver mSettingsObserver;
private final class SettingsObserver extends ContentObserver {
+ private final Uri mShowImeWithHardKeyboardUri =
+ Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
+
+ private final Uri mDisplayInversionEnabledUri =
+ Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
+
public SettingsObserver() {
super(new Handler());
ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
+ resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this);
+ resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this);
}
@Override
- public void onChange(boolean selfChange) {
- updateShowImeWithHardKeyboard();
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mShowImeWithHardKeyboardUri.equals(uri)) {
+ updateShowImeWithHardKeyboard();
+ } else if (mDisplayInversionEnabledUri.equals(uri)) {
+ updateCircularDisplayMaskIfNeeded();
+ }
}
}
static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
boolean mAnimateWallpaperWithTarget;
+ // We give a wallpaper up to 1000ms to finish drawing before playing app transitions.
+ static final long WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION = 1000;
+ static final int WALLPAPER_DRAW_NORMAL = 0;
+ static final int WALLPAPER_DRAW_PENDING = 1;
+ static final int WALLPAPER_DRAW_TIMEOUT = 2;
+ int mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+
AppWindowToken mFocusedApp = null;
PowerManager mPowerManager;
boolean mTurnOnScreen;
+ // Whether or not a layout can cause a wake up when theater mode is enabled.
+ boolean mAllowTheaterModeWakeFromLayout;
+
DragState mDragState = null;
// For frozen screen animations.
* Whether the UI is currently running in touch mode (not showing
* navigational focus because the user is directly pressing the screen).
*/
- boolean mInTouchMode = true;
+ boolean mInTouchMode;
private ViewServer mViewServer;
private final ArrayList<WindowChangeListener> mWindowChangeListeners =
com.android.internal.R.bool.config_sf_limitedAlpha);
mHasPermanentDpad = context.getResources().getBoolean(
com.android.internal.R.bool.config_hasPermanentDpad);
+ mInTouchMode = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_defaultInTouchMode);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- mDisplaySettings = new DisplaySettings(context);
+ mDisplaySettings = new DisplaySettings();
mDisplaySettings.readSettingsLocked();
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
mAnimator = new WindowAnimator(this);
+ mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
+
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
SurfaceControl.closeTransaction();
}
- showCircularDisplayMaskIfNeeded();
+ updateCircularDisplayMaskIfNeeded();
showEmulatorDisplayOverlayIfNeeded();
}
private void placeWindowAfter(WindowState pos, WindowState window) {
final WindowList windows = pos.getWindowList();
final int i = windows.indexOf(pos);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
+ if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
TAG, "Adding window " + window + " at "
+ (i+1) + " of " + windows.size() + " (after " + pos + ")");
windows.add(i+1, window);
private void placeWindowBefore(WindowState pos, WindowState window) {
final WindowList windows = pos.getWindowList();
int i = windows.indexOf(pos);
- if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
+ if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
TAG, "Adding window " + window + " at "
+ i + " of " + windows.size() + " (before " + pos + ")");
if (i < 0) {
//apptoken note that the window could be a floating window
//that was created later or a window at the top of the list of
//windows associated with this token.
- if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
"not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " +
N);
windows.add(newIdx + 1, win);
// Just search for the start of this layer.
final int myLayer = win.mBaseLayer;
int i;
- for (i = 0; i < N; i++) {
+ for (i = N - 1; i >= 0; --i) {
WindowState w = windows.get(i);
- if (w.mBaseLayer > myLayer) {
+ if (w.mBaseLayer <= myLayer) {
break;
}
}
- if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
- "Based on layer: Adding window " + win + " at " + i + " of " + N);
- windows.add(i, win);
+ if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "Based on layer: Adding window " + win + " at " + (i + 1) + " of " + N);
+ windows.add(i + 1, win);
mWindowsChanged = true;
return tokenWindowsPos;
}
// wallpaper during the animation so it doesn't flicker out.
final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
|| (w.mAppToken != null
- && w.mWinAnimator.keyguardGoingAwayAnimation);
+ && w.mWinAnimator.mKeyguardGoingAwayAnimation);
if (hasWallpaper && w.isOnScreen()
&& (mWallpaperTarget == w || w.isDrawFinishedLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
- Rect outContentInsets, InputChannel outInputChannel) {
+ Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
int[] appOp = new int[1];
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
+ if (type == TYPE_ACCESSIBILITY_OVERLAY) {
+ Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token "
+ + attrs.token + ". Aborting.");
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+ }
token = new WindowToken(this, attrs.token, -1, false);
addToken = true;
} else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
+ } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
+ if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
+ Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token "
+ + attrs.token + ". Aborting.");
+ return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+ }
} else if (token.appWindowToken != null) {
Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
// It is not valid to use an app token with other system types; we will
}
}
- win.mWinAnimator.mEnterAnimationPending = true;
+ final WindowStateAnimator winAnimator = win.mWinAnimator;
+ winAnimator.mEnterAnimationPending = true;
+ winAnimator.mEnteringAnimation = true;
if (displayContent.isDefaultDisplay) {
- mPolicy.getContentInsetHintLw(attrs, outContentInsets);
+ mPolicy.getInsetHintLw(win.mAttrs, outContentInsets, outStableInsets);
} else {
outContentInsets.setEmpty();
+ outStableInsets.setEmpty();
}
if (mInTouchMode) {
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
- if (localLOGV) Slog.v(
- TAG, "New client " + client.asBinder()
- + ": window=" + win);
+ if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client "
+ + client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
reportNewConfig = true;
return 0;
}
WindowStateAnimator winAnimator = win.mWinAnimator;
- if (win.mRequestedWidth != requestedWidth
- || win.mRequestedHeight != requestedHeight) {
+ if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth
+ || win.mRequestedHeight != requestedHeight)) {
win.mLayoutNeeded = true;
win.mRequestedWidth = requestedWidth;
win.mRequestedHeight = requestedHeight;
if (oldVisibility == View.GONE) {
winAnimator.mEnterAnimationPending = true;
}
+ winAnimator.mEnteringAnimation = true;
if (toBeDisplayed) {
if ((win.mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== SOFT_INPUT_ADJUST_RESIZE) {
}
} else {
winAnimator.mEnterAnimationPending = false;
+ winAnimator.mEnteringAnimation = false;
if (winAnimator.mSurfaceControl != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
+ ": mExiting=" + win.mExiting);
atoken.layoutConfigChanges = (configChanges &
(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
atoken.mLaunchTaskBehind = launchTaskBehind;
- if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ if (true || DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ " to stack=" + stackId + " task=" + taskId + " at " + addPos);
Task task = mTaskIdToTask.get(taskId);
}
}
- public int getOrientationFromWindowsLocked() {
- if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
- // If the display is frozen, some activities may be in the middle
- // of restarting, and thus have removed their old window. If the
- // window has the flag to hide the lock screen, then the lock screen
- // can re-appear and inflict its own orientation on us. Keep the
- // orientation stable until this all settles down.
- return mLastWindowForcedOrientation;
- }
-
- // TODO(multidisplay): Change to the correct display.
- final WindowList windows = getDefaultWindowListLocked();
- int pos = windows.size() - 1;
- while (pos >= 0) {
- WindowState win = windows.get(pos);
- pos--;
- if (win.mAppToken != null) {
- // We hit an application window. so the orientation will be determined by the
- // app window. No point in continuing further.
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- }
- if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
- continue;
+ public int getOrientationLocked() {
+ if (mDisplayFrozen) {
+ if (mLastWindowForcedOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Display is frozen, return "
+ + mLastWindowForcedOrientation);
+ // If the display is frozen, some activities may be in the middle
+ // of restarting, and thus have removed their old window. If the
+ // window has the flag to hide the lock screen, then the lock screen
+ // can re-appear and inflict its own orientation on us. Keep the
+ // orientation stable until this all settles down.
+ return mLastWindowForcedOrientation;
}
- int req = win.mAttrs.screenOrientation;
- if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
- (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
- continue;
+ } else {
+ // TODO(multidisplay): Change to the correct display.
+ final WindowList windows = getDefaultWindowListLocked();
+ int pos = windows.size() - 1;
+ while (pos >= 0) {
+ WindowState win = windows.get(pos);
+ pos--;
+ if (win.mAppToken != null) {
+ // We hit an application window. so the orientation will be determined by the
+ // app window. No point in continuing further.
+ break;
+ }
+ if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
+ continue;
+ }
+ int req = win.mAttrs.screenOrientation;
+ if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
+ (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
+ continue;
+ }
+
+ if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
+ if (mPolicy.isKeyguardHostWindow(win.mAttrs)) {
+ mLastKeyguardForcedOrientation = req;
+ }
+ return (mLastWindowForcedOrientation = req);
}
+ mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
- if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
- return (mLastWindowForcedOrientation=req);
+ if (mPolicy.isKeyguardLocked()) {
+ // The screen is locked and no top system window is requesting an orientation.
+ // Return either the orientation of the show-when-locked app (if there is any) or
+ // the orientation of the keyguard. No point in searching from the rest of apps.
+ WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
+ AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
+ null : winShowWhenLocked.mAppToken;
+ if (appShowWhenLocked != null) {
+ int req = appShowWhenLocked.requestedOrientation;
+ if (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ req = mLastKeyguardForcedOrientation;
+ }
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + appShowWhenLocked
+ + " -- show when locked, return " + req);
+ return req;
+ }
+ if (DEBUG_ORIENTATION) Slog.v(TAG,
+ "No one is requesting an orientation when the screen is locked");
+ return mLastKeyguardForcedOrientation;
+ }
}
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- }
- public int getOrientationFromAppTokensLocked() {
+ // Top system windows are not requesting an orientation. Start searching from apps.
int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean findingBehind = false;
boolean lastFullscreen = false;
findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
}
}
- if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation");
- return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ if (DEBUG_ORIENTATION) Slog.v(TAG, "No app is requesting an orientation, return "
+ + mForcedAppOrientation);
+ // The next app has not been requested to be visible, so we keep the current orientation
+ // to prevent freezing/unfreezing the display too early.
+ return mForcedAppOrientation;
}
@Override
boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
long ident = Binder.clearCallingIdentity();
try {
- int req = getOrientationFromWindowsLocked();
- if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
- req = getOrientationFromAppTokensLocked();
- }
-
+ int req = getOrientationLocked();
if (req != mForcedAppOrientation) {
mForcedAppOrientation = req;
//send a message to Policy indicating orientation change to take
mAppTransition.prepare();
mStartingIconInTransition = false;
mSkipAppTransitionAnimation = false;
+ }
+ if (mAppTransition.isTransitionSet()) {
mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, 5000);
}
}
@Override
+ public void overridePendingAppTransitionInPlace(String packageName, int anim) {
+ synchronized(mWindowMap) {
+ mAppTransition.overrideInPlaceAppTransition(packageName, anim);
+ }
+ }
+
+ @Override
public void executeAppTransition() {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"executeAppTransition()")) {
return delayed;
}
+ void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
+ if (transit != AppTransition.TRANSIT_UNSET) {
+ if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
+ wtoken.mAppAnimator.animation = null;
+ }
+ applyAnimationLocked(wtoken, null, transit, false, false);
+ }
+ }
+
@Override
public void setAppVisibility(IBinder token, boolean visible) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
}
final long origId = Binder.clearCallingIdentity();
+ wtoken.inPendingTransaction = false;
setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
true, wtoken.voiceInteraction);
wtoken.updateReportedVisibilityLocked();
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
+ wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
- if (delayed) {
+ if (delayed && !wtoken.allAppWindows.isEmpty()) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"removeAppToken make exiting: " + wtoken);
}
}
stack.moveTaskToTop(task);
+ if (mAppTransition.isTransitionSet()) {
+ task.setSendingToBottom(false);
+ }
+ moveStackWindowsLocked(displayContent);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
final TaskStack stack = task.mStack;
stack.moveTaskToBottom(task);
+ if (mAppTransition.isTransitionSet()) {
+ task.setSendingToBottom(true);
+ }
moveStackWindowsLocked(stack.getDisplayContent());
}
} finally {
void removeTaskLocked(Task task) {
final int taskId = task.taskId;
final TaskStack stack = task.mStack;
- if (stack.isAnimating()) {
+ if (!task.mAppTokens.isEmpty() && stack.isAnimating()) {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
task.mDeferRemoval = true;
return;
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
task.mDeferRemoval = false;
- task.mStack.removeTask(task);
+ stack.removeTask(task);
mTaskIdToTask.delete(task.taskId);
+
+ final ArrayList<AppWindowToken> exitingApps = stack.mExitingAppTokens;
+ for (int appNdx = exitingApps.size() - 1; appNdx >= 0; --appNdx) {
+ final AppWindowToken wtoken = exitingApps.get(appNdx);
+ if (wtoken.groupId == taskId) {
+ wtoken.mDeferRemoval = false;
+ exitingApps.remove(appNdx);
+ }
+ }
}
public void removeTask(int taskId) {
@Override
public boolean isKeyguardSecure() {
- return mPolicy.isKeyguardSecure();
+ long origId = Binder.clearCallingIdentity();
+ try {
+ return mPolicy.isKeyguardSecure();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
@Override
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardGoingAway: disableWinAnim="
+ + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade);
synchronized (mWindowMap) {
mAnimator.mKeyguardGoingAway = true;
mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
}
public void keyguardWaitingForActivityDrawn() {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn");
synchronized (mWindowMap) {
mKeyguardWaitingForActivityDrawn = true;
}
}
public void notifyActivityDrawnForKeyguard() {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "notifyActivityDrawnForKeyguard: waiting="
+ + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
synchronized (mWindowMap) {
if (mKeyguardWaitingForActivityDrawn) {
mPolicy.notifyActivityDrawnForKeyguardLw();
}
}
- public void showCircularDisplayMaskIfNeeded() {
+ public void updateCircularDisplayMaskIfNeeded() {
// we're fullscreen and not hosted in an ActivityView
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowIsRound)
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowShowCircularMask)) {
- mH.sendMessage(mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK));
+ // Device configuration calls for a circular display mask, but we only enable the mask
+ // if the accessibility color inversion feature is disabled, as the inverted mask
+ // causes artifacts.
+ int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUserId);
+ int showMask = (inversionState == 1) ? 0 : 1;
+ Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
+ m.arg1 = showMask;
+ mH.sendMessage(m);
}
}
}
}
- public void showCircularMask() {
+ public void showCircularMask(boolean visible) {
synchronized(mWindowMap) {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION showCircularMask");
+ ">>> OPEN TRANSACTION showCircularMask(visible=" + visible + ")");
SurfaceControl.openTransaction();
try {
- // TODO(multi-display): support multiple displays
- if (mCircularDisplayMask == null) {
- int screenOffset = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.circular_display_mask_offset);
-
- mCircularDisplayMask = new CircularDisplayMask(
- getDefaultDisplayContentLocked().getDisplay(),
- mFxSession,
- mPolicy.windowTypeToLayerLw(
- WindowManager.LayoutParams.TYPE_POINTER)
- * TYPE_LAYER_MULTIPLIER + 10, screenOffset);
+ if (visible) {
+ // TODO(multi-display): support multiple displays
+ if (mCircularDisplayMask == null) {
+ int screenOffset = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.circular_display_mask_offset);
+
+ mCircularDisplayMask = new CircularDisplayMask(
+ getDefaultDisplayContentLocked().getDisplay(),
+ mFxSession,
+ mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_POINTER)
+ * TYPE_LAYER_MULTIPLIER + 10, screenOffset);
+ }
+ mCircularDisplayMask.setVisibility(true);
+ } else if (mCircularDisplayMask != null) {
+ mCircularDisplayMask.setVisibility(false);
+ mCircularDisplayMask = null;
}
- mCircularDisplayMask.setVisibility(true);
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION showCircularMask");
+ "<<< CLOSE TRANSACTION showCircularMask(visible=" + visible + ")");
}
}
}
while (true) {
if (retryCount++ > 0) {
+ // Reset max/min layers on retries so we don't accidentally take a screenshot of a
+ // layer based on the previous try.
+ maxLayer = 0;
+ minLayer = Integer.MAX_VALUE;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
continue;
}
} else if (ws.mIsWallpaper) {
- // Fall through.
+ if (appWin == null) {
+ // We have not ran across the target window yet, so it is probably
+ // behind the wallpaper. This can happen when the keyguard is up and
+ // all windows are moved behind the wallpaper. We don't want to
+ // include the wallpaper layer in the screenshot as it will coverup
+ // the layer of the target window.
+ continue;
+ }
+ // Fall through. The target window is in front of the wallpaper. For this
+ // case we want to include the wallpaper layer in the screenshot because
+ // the target window might have some transparent areas.
} else if (appToken != null) {
if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
// This app window is of no interest if it is not associated with the
public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37;
+ public static final int RESET_ANR_MESSAGE = 38;
+ public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
@Override
public void handleMessage(Message msg) {
WindowState lastFocus;
WindowState newFocus;
+ AccessibilityController accessibilityController = null;
+
synchronized(mWindowMap) {
+ // TODO(multidisplay): Accessibility supported only of default desiplay.
+ if (mAccessibilityController != null && getDefaultDisplayContentLocked()
+ .getDisplayId() == Display.DEFAULT_DISPLAY) {
+ accessibilityController = mAccessibilityController;
+ }
+
lastFocus = mLastFocus;
newFocus = mCurrentFocus;
if (lastFocus == newFocus) {
}
}
+ // First notify the accessibility manager for the change so it has
+ // the windows before the newly focused one starts firing eventgs.
+ if (accessibilityController != null) {
+ accessibilityController.onWindowFocusChangedNotLocked();
+ }
+
//System.out.println("Changing focus from " + lastFocus
// + " to " + newFocus);
if (newFocus != null) {
case APP_TRANSITION_TIMEOUT: {
synchronized (mWindowMap) {
- if (mAppTransition.isTransitionSet()) {
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
+ if (mAppTransition.isTransitionSet() || !mOpeningApps.isEmpty()
+ || !mClosingApps.isEmpty()) {
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT."
+ + " isTransitionSet()=" + mAppTransition.isTransitionSet()
+ + " mOpeningApps.size()=" + mOpeningApps.size()
+ + " mClosingApps.size()=" + mClosingApps.size());
mAppTransition.setTimeout();
performLayoutAndPlaceSurfacesLocked();
}
}
case SHOW_CIRCULAR_DISPLAY_MASK: {
- showCircularMask();
+ showCircularMask(msg.arg1 == 1);
break;
}
break;
case TAP_OUTSIDE_STACK: {
- int stackId;
- synchronized (mWindowMap) {
- stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
- }
- if (stackId >= 0) {
- try {
- mActivityManager.setFocusedStack(stackId);
- } catch (RemoteException e) {
- }
- }
+// int stackId;
+// synchronized (mWindowMap) {
+// stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
+// }
+// if (stackId >= 0) {
+// try {
+// mActivityManager.setFocusedStack(stackId);
+// } catch (RemoteException e) {
+// }
+// }
}
break;
case NOTIFY_ACTIVITY_DRAWN:
}
}
break;
+ case RESET_ANR_MESSAGE: {
+ synchronized (mWindowMap) {
+ mLastANRState = null;
+ }
+ }
+ break;
+ case WALLPAPER_DRAW_PENDING_TIMEOUT: {
+ synchronized (mWindowMap) {
+ if (mWallpaperDrawState == WALLPAPER_DRAW_PENDING) {
+ mWallpaperDrawState = WALLPAPER_DRAW_TIMEOUT;
+ if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+ "*** WALLPAPER DRAW TIMEOUT");
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
displayInfo.overscanBottom = bottom;
}
- mDisplaySettings.setOverscanLocked(displayInfo.name, left, top, right, bottom);
+ mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, left, top, right, bottom);
mDisplaySettings.writeSettingsLocked();
reconfigureDisplayLocked(displayContent);
"Checking " + NN + " opening apps (frozen="
+ mDisplayFrozen + " timeout="
+ mAppTransition.isTimeout() + ")...");
- if (!mDisplayFrozen && !mAppTransition.isTimeout()) {
- // If the display isn't frozen, wait to do anything until
- // all of the apps are ready. Otherwise just go because
- // we'll unfreeze the display when everyone is ready.
+ if (!mAppTransition.isTimeout()) {
for (i=0; i<NN && goodToGo; i++) {
AppWindowToken wtoken = mOpeningApps.valueAt(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
goodToGo = false;
}
}
+ if (goodToGo && isWallpaperVisible(mWallpaperTarget)) {
+ boolean wallpaperGoodToGo = true;
+ for (int curTokenIndex = mWallpaperTokens.size() - 1;
+ curTokenIndex >= 0 && wallpaperGoodToGo; curTokenIndex--) {
+ WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ for (int curWallpaperIndex = token.windows.size() - 1; curWallpaperIndex >= 0;
+ curWallpaperIndex--) {
+ WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
+ // We've told this wallpaper to be visible, but it is not drawn yet
+ wallpaperGoodToGo = false;
+ if (mWallpaperDrawState != WALLPAPER_DRAW_TIMEOUT) {
+ // wait for this wallpaper until it is drawn or timeout
+ goodToGo = false;
+ }
+ if (mWallpaperDrawState == WALLPAPER_DRAW_NORMAL) {
+ mWallpaperDrawState = WALLPAPER_DRAW_PENDING;
+ mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
+ mH.sendEmptyMessageDelayed(H.WALLPAPER_DRAW_PENDING_TIMEOUT,
+ WALLPAPER_DRAW_PENDING_TIMEOUT_DURATION);
+ }
+ if (DEBUG_APP_TRANSITIONS || DEBUG_WALLPAPER) Slog.v(TAG,
+ "Wallpaper should be visible but has not been drawn yet. " +
+ "mWallpaperDrawState=" + mWallpaperDrawState);
+ break;
+ }
+ }
+ }
+ if (wallpaperGoodToGo) {
+ mWallpaperDrawState = WALLPAPER_DRAW_NORMAL;
+ mH.removeMessages(H.WALLPAPER_DRAW_PENDING_TIMEOUT);
+ }
+ }
}
if (goodToGo) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
int topOpeningLayer = 0;
int topClosingLayer = 0;
+ // Process all applications animating in place
+ if (transit == AppTransition.TRANSIT_TASK_IN_PLACE) {
+ // Find the focused window
+ final WindowState win =
+ findFocusedWindowLocked(getDefaultDisplayContentLocked());
+ if (win != null) {
+ final AppWindowToken wtoken = win.mAppToken;
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken);
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
+ updateTokenInPlaceLocked(wtoken, transit);
+ wtoken.updateReportedVisibilityLocked();
+
+ appAnimator.mAllAppWinAnimators.clear();
+ final int N = wtoken.allAppWindows.size();
+ for (int j = 0; j < N; j++) {
+ appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
+ }
+ mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ }
+ }
+
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.valueAt(i);
topClosingLayer);
openingAppAnimator.deferThumbnailDestruction =
!mAppTransition.isNextThumbnailTransitionScaleUp();
- if (openingAppAnimator.deferThumbnailDestruction) {
- if (closingAppAnimator != null &&
- closingAppAnimator.animation != null) {
- closingAppAnimator.deferredThumbnail = surfaceControl;
- }
- }
} else {
anim = mAppTransition.createThumbnailScaleAnimationLocked(
displayInfo.appWidth, displayInfo.appHeight, transit);
}
updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, true /*updateInputWindows*/);
mFocusMayChange = false;
+ notifyActivityDrawnForKeyguard();
}
return changes;
final int type = attrs.type;
if (canBeSeen
&& (type == TYPE_SYSTEM_DIALOG
- || type == TYPE_RECENTS_OVERLAY
|| type == TYPE_SYSTEM_ERROR
|| (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
mInnerFields.mSyswin = true;
+ " interesting=" + numInteresting
+ " drawn=" + wtoken.numDrawnWindows);
wtoken.allDrawn = true;
+ // Force an additional layout pass where WindowStateAnimator#
+ // commitFinishDrawingLocked() will call performShowLocked().
+ displayContent.layoutNeeded = true;
mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, wtoken.token).sendToTarget();
}
}
w.mContentChanged = false;
// Moved from updateWindowsAndWallpaperLocked().
- if (w.mHasSurface) {
+ if (w.mHasSurface && !w.isHiddenFromUserLocked()) {
// Take care of the window being ready to display.
final boolean committed =
winAnimator.commitFinishDrawingLocked(currentTime);
atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
atoken.startingDisplayed = false;
}
- if ((w.isOnScreen() || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
+ if ((w.isOnScreenIgnoringKeyguard()
+ || winAnimator.mAttrType == TYPE_BASE_APPLICATION)
&& !w.mExiting && !w.mDestroying) {
if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
if (!w.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
+ " pv=" + w.mPolicyVisibility
- + " mDrawState=" + winAnimator.mDrawState
+ + " mDrawState=" + winAnimator.drawStateToString()
+ " ah=" + w.mAttachedHidden
+ " th=" + atoken.hiddenRequested
+ " a=" + winAnimator.mAnimating);
mStackIdToStack.valueAt(stackNdx).mExitingAppTokens;
for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
AppWindowToken token = exitingAppTokens.get(i);
- if (!token.hasVisible && !mClosingApps.contains(token) && !token.mDeferRemoval) {
+ if (!token.hasVisible && !mClosingApps.contains(token) &&
+ (!token.mDeferRemoval || token.allAppWindows.isEmpty())) {
// Make sure there is no animation running on this token,
// so any windows associated with it will be removed as
// soon as their animations are complete
"performLayout: App token exiting now removed" + token);
removeAppFromTaskLocked(token);
exitingAppTokens.remove(i);
+ final Task task = mTaskIdToTask.get(token.groupId);
+ if (task != null && task.mDeferRemoval && task.mAppTokens.isEmpty()) {
+ removeTaskLocked(task);
+ }
}
}
}
}
if (mTurnOnScreen) {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ if (mAllowTheaterModeWakeFromLayout
+ || Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0) == 0) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ }
mTurnOnScreen = false;
}
mCurrentFocus = newFocus;
mLosingFocus.remove(newFocus);
- // TODO(multidisplay): Accessibilty supported only of default desiplay.
- if (mAccessibilityController != null
- && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
- mAccessibilityController.onWindowFocusChangedLocked();
- }
-
int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
if (imWindowChanged && oldFocus != mInputMethodWindow) {
}
if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen
- || mClientFreezingScreen) {
+ || mClientFreezingScreen || !mOpeningApps.isEmpty()) {
if (DEBUG_ORIENTATION) Slog.d(TAG,
"stopFreezingDisplayLocked: Returning mWaitingForConfig=" + mWaitingForConfig
+ ", mAppsFreezingScreen=" + mAppsFreezingScreen
+ ", mWindowsFreezingScreen=" + mWindowsFreezingScreen
- + ", mClientFreezingScreen=" + mClientFreezingScreen);
+ + ", mClientFreezingScreen=" + mClientFreezingScreen
+ + ", mOpeningApps.size()=" + mOpeningApps.size());
return;
}
boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) {
synchronized (mWindowMap) {
FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
- name, windowType,
- layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
- hasFocus, touchFullscreen);
+ name, windowType, layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen);
int i=0;
while (i<mFakeWindows.size()) {
if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
}
pw.println();
dumpWindowsNoHeaderLocked(pw, true, null);
+ pw.println();
+ pw.println("Last ANR continued");
+ dumpDisplayContentsLocked(pw, true);
pw.close();
mLastANRState = sw.toString();
+
+ mH.removeMessages(H.RESET_ANR_MESSAGE);
+ mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS);
}
@Override
DisplayInfo displayInfo = displayContent.getDisplayInfo();
final Rect rect = new Rect();
- mDisplaySettings.getOverscanLocked(displayInfo.name, rect);
+ mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
synchronized (displayContent.mDisplaySizeLock) {
displayInfo.overscanLeft = rect.left;
displayInfo.overscanTop = rect.top;
checkDrawnWindowsLocked();
}
}
+
+ @Override
+ public void addWindowToken(IBinder token, int type) {
+ WindowManagerService.this.addWindowToken(token, type);
+ }
+
+ @Override
+ public void removeWindowToken(IBinder token, boolean removeWindows) {
+ synchronized(mWindowMap) {
+ if (removeWindows) {
+ WindowToken wtoken = mTokenMap.remove(token);
+ if (wtoken != null) {
+ wtoken.removeAllWindows();
+ }
+ }
+ WindowManagerService.this.removeWindowToken(token);
+ }
+ }
}
}