1、findDesiredInputMethodWindowIndexLocked()
从名字可以出来,这个函数是寻找InputMethodWindow要放置的位置,分析这个函数后自然就知道对于输入法窗口的排列规则。
int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
WindowList windows = getDefaultWindowListLocked();
WindowState w = null;
int i;
for (i = windows.size() - 1; i >= 0; --i) { //①从窗口列表的最顶端开始遍历窗口列表,如果该窗口可以成为IME Target,那么该循环退出,即遍历出第一个输入法目标窗口保存在W中,w也可能是mWindows[0];什么情况下窗口才可以成为IME的Target呢?情况一:窗口属性都没有设置FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM属性;情况二:窗口属性同时设置了FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM属性;情况三:TYPE_APPLICATION_STARTING类型窗口也可以作为IME的Target;
WindowState win = windows.get(i);
if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i
+ " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
if (canBeImeTarget(win)) { //②如果遍历到一个窗口可以作为IME 的Target,正常情况下那么该Target之上的窗口位置便是输入法位置,特殊情况便是下面那些矫正逻辑,不必太过关心;
w = win;
//Slog.i(TAG, "Putting input method here!");
// Yet more tricksyness! If this window is a "starting"
// window, we do actually want to be on top of it, but
// it is not -really- where input will go. So if the caller
// is not actually looking to move the IME, look down below
// for a real window to target...
if (!willMove
&& w.mAttrs.type == TYPE_APPLICATION_STARTING
&& i > 0) {
WindowState wb = windows.get(i-1);
if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
i--;
w = wb;
}
}
break;
}
}
// Now w is either mWindows[0] or an IME (or null if mWindows is empty).
if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w);
// Now, a special case -- if the last target's window is in the
// process of exiting, and is above the new target, keep on the
// last target to avoid flicker. Consider for example a Dialog with
// the IME shown: when the Dialog is dismissed, we want to keep
// the IME above it until it is completely gone so it doesn't drop
// behind the dialog or its full-screen scrim.
final WindowState curTarget = mInputMethodTarget;
if (curTarget != null
&& curTarget.isDisplayedLw()
&& curTarget.isClosing()
&& (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, not changing");
return windows.indexOf(curTarget) + 1;
}
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
+ w + " willMove=" + willMove);
if (willMove && w != null) {
AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
if (token != null) {
// Now some fun for dealing with window animations that
// modify the Z order. We need to look at all windows below
// the current target that are in this app, finding the highest
// visible one in layering.
WindowState highestTarget = null;
int highestPos = 0;
if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
WindowList curWindows = curTarget.getWindowList();
int pos = curWindows.indexOf(curTarget);
while (pos >= 0) {
WindowState win = curWindows.get(pos);
if (win.mAppToken != token) {
break;
}
if (!win.mRemoved) {
if (highestTarget == null || win.mWinAnimator.mAnimLayer >
highestTarget.mWinAnimator.mAnimLayer) {
highestTarget = win;
highestPos = pos;
}
}
pos--;
}
}
if (highestTarget != null) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, mAppTransition + " " + highestTarget
+ " animating=" + highestTarget.mWinAnimator.isAnimating()
+ " layer=" + highestTarget.mWinAnimator.mAnimLayer
+ " new layer=" + w.mWinAnimator.mAnimLayer);
if (mAppTransition.isTransitionSet()) {
// If we are currently setting up for an animation,
// hold everything until we can find out what will happen.
mInputMethodTargetWaitingAnim = true;
mInputMethodTarget = highestTarget;
return highestPos + 1;
} else if (highestTarget.mWinAnimator.isAnimating() &&
highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
// If the window we are currently targeting is involved
// with an animation, and it is on top of the next target
// we will be over, then hold off on moving until
// that is done.
mInputMethodTargetWaitingAnim = true;
mInputMethodTarget = highestTarget;
return highestPos + 1;
}
}
}
}
//Slog.i(TAG, "Placing input method @" + (i+1));
if (w != null) {
if (willMove) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to "
+ w + (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
mInputMethodTarget = w;
mInputMethodTargetWaitingAnim = false;
if (w.mAppToken != null) {
setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
} else {
setInputMethodAnimLayerAdjustment(0);
}
}
return i+1;
}
if (willMove) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG, "Moving IM target from " + curTarget + " to null."
+ (HIDE_STACK_CRAWLS ? "" : " Callers=" + Debug.getCallers(4)));
mInputMethodTarget = null;
setInputMethodAnimLayerAdjustment(0);
}
return -1;
}
总结:只有参数willMove为true时mInputMethodTarget才有可能更改。正常情况下一般找到IME Target便可以确定输入法窗口位置便是Target之上的位置,特殊情况就不用仔细研究了,如果找不到IME Target便return -1。只要知道该函数return一个输入法位置,并且找到mInputMethodTarget窗口(输入法目标窗口)。把这个函数简化下就是从窗口列表中找到最顶位置并且canBeImeTarget()的窗口作为输入法目标窗口,输入法窗口位置等于输入法目标窗口位置+1.
2、moveInputMethodWindowsIfNeededLocked()
boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
final WindowState imWin = mInputMethodWindow;
final int DN = mInputMethodDialogs.size();
if (imWin == null && DN == 0) {
return false;
}
// TODO(multidisplay): IMEs are only supported on the default display.
WindowList windows = getDefaultWindowListLocked();
int imPos = findDesiredInputMethodWindowIndexLocked(true); //①寻找输入法窗口位置;
if (imPos >= 0) { //②如果找到输入法窗口要放置的位置;
// In this case, the input method windows are to be placed
// immediately above the window they are targeting.
// First check to see if the input method windows are already
// located here, and contiguous.
final int N = windows.size();
WindowState firstImWin = imPos < N
? windows.get(imPos) : null;
// Figure out the actual input method window that should be
// at the bottom of their stack.
WindowState baseImWin = imWin != null
? imWin : mInputMethodDialogs.get(0);
if (baseImWin.mChildWindows.size() > 0) {
WindowState cw = baseImWin.mChildWindows.get(0);
if (cw.mSubLayer < 0) baseImWin = cw;
}
if (firstImWin == baseImWin) { //③这个if逻辑就是判断输入法窗口是否处在①中找到的位置上 ,并且输入法窗口及输入法对话窗口是否连续,如果位置正确并且连续,自然无需重新移动输入法窗口;
// The windows haven't moved... but are they still contiguous?
// First find the top IM window.
int pos = imPos+1;
while (pos < N) {
if (!(windows.get(pos)).mIsImWindow) {
break;
}
pos++;
}
pos++;
// Now there should be no more input method windows above.
while (pos < N) {
if ((windows.get(pos)).mIsImWindow) {
break;
}
pos++;
}
if (pos >= N) { //④如果这个条件满足,自然是输入法窗口位置正确,并且所有输入法窗口连续;
// Z order is good.
// The IM target window may be changed, so update the mTargetAppToken.
if (imWin != null) {
imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
}
return false;
}
}
if (imWin != null) { //⑤如果④中条件无法满足,那么自然需要重新排列输入法窗口位置;
if (DEBUG_INPUT_METHOD) {
Slog.v(TAG, "Moving IM from " + imPos);
logWindowList(windows, " ");
}
imPos = tmpRemoveWindowLocked(imPos, imWin); //⑥移除输入法窗口,imPos作为参数穿进去,如果移除的窗口位于imPos之下,那么imPos-=移除窗口数;如果移除的窗口在imPos之上,那么imPos值不变;imPos值后续会用来作为插入输入法窗口位置,Google写代码真牛啊!
if (DEBUG_INPUT_METHOD) {
Slog.v(TAG, "List after removing with new pos " + imPos + ":");
logWindowList(windows, " ");
}
imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
reAddWindowLocked(imPos, imWin); //⑦重新add输入法窗口到正确的位置上去,下面如果还有输入法对话框窗口,那么add到输入法窗口上一个位置,紧邻;
if (DEBUG_INPUT_METHOD) {
Slog.v(TAG, "List after moving IM to " + imPos + ":");
logWindowList(windows, " ");
}
if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
} else {
moveInputMethodDialogsLocked(imPos);
}
} else { //如果输入法窗口位置未找到,那么对于输入法窗口来说,imWin.mTargetAppToken置空,先调用tmpRemoveWindowLocked()将输入法窗口及子窗口remove,然后再调用reAddWindowToListInOrderLocked()重新add进来;
// In this case, the input method windows go in a fixed layer,
// because they aren't currently associated with a focus window.
if (imWin != null) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
tmpRemoveWindowLocked(0, imWin);
imWin.mTargetAppToken = null;
reAddWindowToListInOrderLocked(imWin);
if (DEBUG_INPUT_METHOD) {
Slog.v(TAG, "List with no IM target:");
logWindowList(windows, " ");
}
if (DN > 0) moveInputMethodDialogsLocked(-1);
} else {
moveInputMethodDialogsLocked(-1);
}
}
if (needAssignLayers) {
assignLayersLocked(windows);
}
return true;
}
总结:该函数首先判断输入法窗口是否在正确的位置上,同时是否连续,这样就无需重排;如果要重排,分两种情况,一种是知道输入法窗口要放置的位置,此时先把输入法窗口先进行移除,然后add到要放置的位置即可,一种情况是找不到输入法窗口放置位置,此时也是先把输入法窗口移除,然后调用reAddWindowToListInOrderLocked()添加到窗口列表中,对于输入法对话框窗口,移动到窗口列表的最底部去;
第二部分、壁纸窗口管理
1、只要mWallpaperTarget不为null,那么壁纸就可见。因为WindowState.mObscured一般为false。
final boolean isWallpaperVisible(WindowState wallpaperTarget) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
+ " upper=" + mUpperWallpaperTarget
+ " lower=" + mLowerWallpaperTarget);
return (wallpaperTarget != null
&& (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
&& wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
|| mUpperWallpaperTarget != null
|| mLowerWallpaperTarget != null;
}
2、寻找mWallpaperTarget的逻辑
int adjustWallpaperWindowsLocked() {
mInnerFields.mWallpaperMayChange = false;
boolean targetChanged = false;
// TODO(multidisplay): Wallpapers on main screen only.
final DisplayInfo displayInfo = getDefaultDisplayContentLocked().getDisplayInfo();
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
// First find top-most window that has asked to be on top of the
// wallpaper; all wallpapers go behind it.
final WindowList windows = getDefaultWindowListLocked(); //获取窗口堆栈;
int N = windows.size();
WindowState w = null;
WindowState foundW = null;
int foundI = 0;
WindowState topCurW = null;
int topCurI = 0;
int windowDetachedI = -1;
int i = N;
while (i > 0) { //从窗口堆栈顶端开始查找一个带FLAG_SHOW_WALLPAPER属性的可见的绘制完成的窗口,我们把它称作“壁纸目标窗口”,壁纸窗口将会显示在“壁纸目标窗口”之下;
i--;
w = windows.get(i);
if ((w.mAttrs.type == TYPE_WALLPAPER)) {
if (topCurW == null) {
topCurW = w;
topCurI = i;
}
continue;
}
topCurW = null;
if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
// If this window's app token is hidden and not animating,
// it is of no interest to us.
if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
if (DEBUG_WALLPAPER) Slog.v(TAG,
"Skipping hidden and not animating token: " + w);
continue;
}
}
if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
+ w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
// If the app is executing an animation because the keyguard is going away, keep the
// 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.mKeyguardGoingAwayAnimation);
if (hasWallpaper && w.isOnScreen()
&& (mWallpaperTarget == w || w.isDrawFinishedLw())) { //如果找到了一个“壁纸目标窗口”,那么结束while循环,并记录在局部变量foundW和foundI中,foundI指向目标壁纸窗口在窗口堆栈中的位置。如果while循环结束了还没找到,那么foundW=null,foundI=0;
if (DEBUG_WALLPAPER) Slog.v(TAG,
"Found wallpaper target: #" + i + "=" + w);
foundW = w;
foundI = i;
if (w == mWallpaperTarget && w.mWinAnimator.isAnimating()) {
// The current wallpaper target is animating, so we'll
// look behind it for another possible target and figure
// out what is going on below.
if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
+ ": token animating, looking behind.");
continue;
}
break;
} else if (w == mAnimator.mWindowDetachedWallpaper) {
windowDetachedI = i;
}
}
if (foundW == null && windowDetachedI >= 0) {
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
"Found animating detached wallpaper activity: #" + i + "=" + w);
foundW = w;
foundI = windowDetachedI;
}
if (mWallpaperTarget != foundW
&& (mLowerWallpaperTarget == null || mLowerWallpaperTarget != foundW)) { //“壁纸目标窗口”该更新了
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "New wallpaper target: " + foundW
+ " oldTarget: " + mWallpaperTarget);
}
mLowerWallpaperTarget = null;
mUpperWallpaperTarget = null;
WindowState oldW = mWallpaperTarget;
mWallpaperTarget = foundW;
targetChanged = true;
//按理说走到上面这个逻辑就结束,但是有一个特殊case就是oldW和foundW均不为null,且都在做动画,比如keyguard解锁时就是这种情况,oldW指向StatesBar,foundW指向launcher3;
// Now what is happening... if the current and new targets are
// animating, then we are in our super special mode!
if (foundW != null && oldW != null) {
boolean oldAnim = oldW.isAnimatingLw();
boolean foundAnim = foundW.isAnimatingLw();
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "New animation: " + foundAnim
+ " old animation: " + oldAnim);
}
if (foundAnim && oldAnim) {
int oldI = windows.indexOf(oldW);
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
}
if (oldI >= 0) {
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "Animating wallpapers: old#" + oldI
+ "=" + oldW + "; new#" + foundI
+ "=" + foundW);
}
// Set the new target correctly.
if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "Old wallpaper still the target.");
}
mWallpaperTarget = oldW;
foundW = oldW;
foundI = oldI;
}
// Now set the upper and lower wallpaper targets
// correctly, and make sure that we are positioning
// the wallpaper below the lower.
else if (foundI > oldI) {
// The new target is on top of the old one.
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "Found target above old target.");
}
mUpperWallpaperTarget = foundW;
mLowerWallpaperTarget = oldW;
foundW = oldW;
foundI = oldI;
} else {
// The new target is below the old one.
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "Found target below old target.");
}
mUpperWallpaperTarget = oldW;
mLowerWallpaperTarget = foundW;
}
}
}
}
} else if (mLowerWallpaperTarget != null) {
// Is it time to stop animating?
if (!mLowerWallpaperTarget.isAnimatingLw() || !mUpperWallpaperTarget.isAnimatingLw()) {
if (DEBUG_WALLPAPER_LIGHT) {
Slog.v(TAG, "No longer animating wallpaper targets!");
}
mLowerWallpaperTarget = null;
mUpperWallpaperTarget = null;
mWallpaperTarget = foundW;
targetChanged = true;
}
}
boolean visible = foundW != null;
if (visible) { //如果存在“目标壁纸窗口”,那么visible就为true;
// The window is visible to the compositor... but is it visible
// to the user? That is what the wallpaper cares about.
visible = isWallpaperVisible(foundW); //该函数决策是否需要将壁纸设为可见;
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
// If the wallpaper target is animating, we may need to copy
// its layer adjustment. Only do this if we are not transfering
// between two wallpaper targets.
mWallpaperAnimLayerAdjustment =
(mLowerWallpaperTarget == null && foundW.mAppToken != null)
? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
final int maxLayer = mPolicy.getMaxWallpaperLayer()
* TYPE_LAYER_MULTIPLIER
+ TYPE_LAYER_OFFSET;
// Now w is the window we are supposed to be behind... but we
// need to be sure to also be behind any of its attached windows,
// AND any starting window associated with it, AND below the
// maximum layer the policy allows for wallpapers.
while (foundI > 0) { //该循环用于检查找到的“壁纸目标窗口”是否是子窗口,如果是子窗口,那么将foundW指向父窗口,壁纸窗口必须放在父窗口下面;
WindowState wb = windows.get(foundI-1);
if (wb.mBaseLayer < maxLayer &&
wb.mAttachedWindow != foundW &&
(foundW.mAttachedWindow == null ||
wb.mAttachedWindow != foundW.mAttachedWindow) &&
(wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
foundW.mToken == null || wb.mToken != foundW.mToken)) {
// This window is not related to the previous one in any
// interesting way, so stop here.
break;
}
foundW = wb;
foundI--;
}
} else {
if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
}
if (foundW == null && topCurW != null) { //如果没有找到“壁纸目标窗口”,并且存在壁纸窗口,那么将foundW指向壁纸窗口、foundI指向壁纸窗口的上一个窗口位置;
// There is no wallpaper target, so it goes at the bottom.
// We will assume it is the same place as last time, if known.
foundW = topCurW;
foundI = topCurI+1;
} else {
// Okay i is the position immediately above the wallpaper. Look at
// what is below it for later.
foundW = foundI > 0 ? windows.get(foundI-1) : null;
}
if (visible) {
if (mWallpaperTarget.mWallpaperX >= 0) {
mLastWallpaperX = mWallpaperTarget.mWallpaperX;
mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
}
if (mWallpaperTarget.mWallpaperY >= 0) {
mLastWallpaperY = mWallpaperTarget.mWallpaperY;
mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
}
if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
}
if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
}
}
// Start stepping backwards from here, ensuring that our wallpaper windows
// are correctly placed.
int changed = 0;
int curTokenIndex = mWallpaperTokens.size(); //mWallpaperTokens中保存着壁纸窗口Token,只有一个对象;
while (curTokenIndex > 0) {
curTokenIndex--;
WindowToken token = mWallpaperTokens.get(curTokenIndex);
if (token.hidden == visible) {
if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
"Wallpaper token " + token + " hidden=" + !visible);
changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
token.hidden = !visible;
// Need to do a layout to ensure the wallpaper now has the
// correct size.
getDefaultDisplayContentLocked().layoutNeeded = true;
}
int curWallpaperIndex = token.windows.size();
while (curWallpaperIndex > 0) { //壁纸窗口Token只有一个壁纸窗口;
curWallpaperIndex--;
WindowState wallpaper = token.windows.get(curWallpaperIndex);
if (visible) {
updateWallpaperOffsetLocked(wallpaper, dw, dh, false); //更新壁纸窗口偏移;
}
// First, make sure the client has the current visibility
// state.
dispatchWallpaperVisibility(wallpaper, visible); //通知壁纸窗口当前的可见性,如果变为可见,那么壁纸必然需要更新绘制;
wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+ wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
// First, if this window is at the current index, then all
// is well.
if (wallpaper == foundW) {
foundI--;
foundW = foundI > 0
? windows.get(foundI-1) : null;
continue;
}
// The window didn't match... the current wallpaper window,
// wherever it is, is in the wrong place, so make sure it is
// not in the list.
int oldIndex = windows.indexOf(wallpaper);
if (oldIndex >= 0) {
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
+ oldIndex + ": " + wallpaper);
windows.remove(oldIndex);
mWindowsChanged = true;
if (oldIndex < foundI) {
foundI--;
}
}
// Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
// layer. For keyguard over wallpaper put the wallpaper under the keyguard.
int insertionIndex = 0;
if (visible && foundW != null) { //如果“目标窗口壁纸”为keyguard,那么直接插入keyguard窗口之下;否则直接放到窗口堆栈最底下;
final int type = foundW.mAttrs.type;
final int privateFlags = foundW.mAttrs.privateFlags;
if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
|| type == TYPE_KEYGUARD_SCRIM) {
insertionIndex = windows.indexOf(foundW);
}
}
if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
Slog.v(TAG, "Moving wallpaper " + wallpaper
+ " from " + oldIndex + " to " + insertionIndex);
}
windows.add(insertionIndex, wallpaper);
mWindowsChanged = true;
changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
}
}
/*
final TaskStack targetStack =
mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
targetStack != null && !targetStack.isHomeStack()) {
// If the wallpaper target is not on the home stack then make sure that all windows
// from other non-home stacks are above the wallpaper.
for (i = foundI - 1; i >= 0; --i) {
WindowState win = windows.get(i);
if (!win.isVisibleLw()) {
continue;
}
final TaskStack winStack = win.getStack();
if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
windows.remove(i);
windows.add(foundI + 1, win);
}
}
}
*/
if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
+ " lower=" + mLowerWallpaperTarget + " upper="
+ mUpperWallpaperTarget);
}
return changed;
}