blob: 4541dd6030b6b3f1877fec5c7db4d309c00af767 [file] [log] [blame]
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Craig Mautner42bf39e2014-02-21 16:46:22 -080019import static com.android.server.wm.WindowManagerService.TAG;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070020import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
Craig Mautnere3119b72015-01-20 15:02:36 -080021import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
Stefan Kuhne234dbf82015-08-13 09:44:28 -070022import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
Craig Mautner42bf39e2014-02-21 16:46:22 -080023
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070024import android.content.res.Configuration;
25import android.graphics.Rect;
Craig Mautner2c2549c2013-11-12 08:31:15 -080026import android.util.EventLog;
Craig Mautner42bf39e2014-02-21 16:46:22 -080027import android.util.Slog;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070028import android.util.SparseArray;
29import android.util.TypedValue;
30import android.view.DisplayInfo;
31import android.view.Surface;
32
Craig Mautnere3119b72015-01-20 15:02:36 -080033import com.android.server.EventLogTags;
Craig Mautner2c2549c2013-11-12 08:31:15 -080034
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070035import java.io.PrintWriter;
36import java.util.ArrayList;
37
38class Task implements DimLayer.DimLayerUser {
39 /** Amount of time in milliseconds to animate the dim surface from one value to another,
40 * when no window animation is driving it. */
41 private static final int DEFAULT_DIM_DURATION = 200;
42
Wale Ogunwale2cc92f52015-09-09 13:12:10 -070043 // Return value from {@link setBounds} indicating no change was made to the Task bounds.
44 static final int BOUNDS_CHANGE_NONE = 0;
45 // Return value from {@link setBounds} indicating the position of the Task bounds changed.
46 static final int BOUNDS_CHANGE_POSITION = 1;
47 // Return value from {@link setBounds} indicating the size of the Task bounds changed.
48 static final int BOUNDS_CHANGE_SIZE = 1 << 1;
49
Craig Mautnerc00204b2013-03-05 15:02:14 -080050 TaskStack mStack;
Craig Mautner05d6272ba2013-02-11 09:39:27 -080051 final AppTokenList mAppTokens = new AppTokenList();
Craig Mautner83162a92015-01-26 14:43:30 -080052 final int mTaskId;
Craig Mautnerac6f8432013-07-17 13:24:59 -070053 final int mUserId;
Craig Mautner9ef471f2014-02-07 13:11:47 -080054 boolean mDeferRemoval = false;
Craig Mautnere3119b72015-01-20 15:02:36 -080055 final WindowManagerService mService;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080056
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070057 // Content limits relative to the DisplayContent this sits in.
58 private Rect mBounds = new Rect();
59
60 // Device rotation as of the last time {@link #mBounds} was set.
61 int mRotation;
62
63 // Whether mBounds is fullscreen
64 private boolean mFullscreen = true;
65
66 // Contains configurations settings that are different from the global configuration due to
67 // stack specific operations. E.g. {@link #setBounds}.
68 Configuration mOverrideConfig;
69
70 // For comparison with DisplayContent bounds.
71 private Rect mTmpRect = new Rect();
72 // For handling display rotations.
73 private Rect mTmpRect2 = new Rect();
74
Chong Zhang3005e752015-09-18 18:46:28 -070075 // Whether the task is currently being drag-resized
76 private boolean mDragResizing;
77
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070078 // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
79 WindowStateAnimator mDimWinAnimator;
80 // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
81 private DimLayer mDimLayer;
82 // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end
83 // then stop any dimming.
84 private boolean mContinueDimming;
85 // Shared dim layer for fullscreen tasks. {@link #mDimLayer} will point to this instead
86 // of creating a new object per fullscreen task on a display.
87 private static final SparseArray<DimLayer> sSharedFullscreenDimLayers = new SparseArray<>();
88
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070089 Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
90 Configuration config) {
Craig Mautner83162a92015-01-26 14:43:30 -080091 mTaskId = taskId;
Craig Mautnerc00204b2013-03-05 15:02:14 -080092 mStack = stack;
Craig Mautnerac6f8432013-07-17 13:24:59 -070093 mUserId = userId;
Craig Mautnere3119b72015-01-20 15:02:36 -080094 mService = service;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070095 setBounds(bounds, config);
Craig Mautnerc00204b2013-03-05 15:02:14 -080096 }
97
98 DisplayContent getDisplayContent() {
99 return mStack.getDisplayContent();
100 }
101
102 void addAppToken(int addPos, AppWindowToken wtoken) {
Craig Mautner42bf39e2014-02-21 16:46:22 -0800103 final int lastPos = mAppTokens.size();
Craig Mautner83162a92015-01-26 14:43:30 -0800104 if (addPos >= lastPos) {
105 addPos = lastPos;
106 } else {
107 for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
108 if (mAppTokens.get(pos).removed) {
109 // addPos assumes removed tokens are actually gone.
110 ++addPos;
111 }
Craig Mautner01f79cf2014-08-27 09:56:02 -0700112 }
Craig Mautner42bf39e2014-02-21 16:46:22 -0800113 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800114 mAppTokens.add(addPos, wtoken);
Craig Mautner83162a92015-01-26 14:43:30 -0800115 wtoken.mTask = this;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800116 mDeferRemoval = false;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800117 }
118
Craig Mautnere3119b72015-01-20 15:02:36 -0800119 void removeLocked() {
120 if (!mAppTokens.isEmpty() && mStack.isAnimating()) {
Craig Mautner83162a92015-01-26 14:43:30 -0800121 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
Craig Mautnere3119b72015-01-20 15:02:36 -0800122 mDeferRemoval = true;
123 return;
124 }
Craig Mautner83162a92015-01-26 14:43:30 -0800125 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
126 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
Craig Mautnere3119b72015-01-20 15:02:36 -0800127 mDeferRemoval = false;
128 mStack.removeTask(this);
Craig Mautner83162a92015-01-26 14:43:30 -0800129 mService.mTaskIdToTask.delete(mTaskId);
Craig Mautnere3119b72015-01-20 15:02:36 -0800130 }
131
Wale Ogunwale53a29a92015-02-23 15:42:52 -0800132 void moveTaskToStack(TaskStack stack, boolean toTop) {
133 if (stack == mStack) {
134 return;
135 }
136 if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
137 + " from stack=" + mStack);
Wale Ogunwale000957c2015-04-03 08:19:12 -0700138 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
Wale Ogunwale53a29a92015-02-23 15:42:52 -0800139 if (mStack != null) {
140 mStack.removeTask(this);
141 }
142 stack.addTask(this, toTop);
143 }
144
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700145 void positionTaskInStack(TaskStack stack, int position) {
146 if (mStack != null && stack != mStack) {
147 if (DEBUG_STACK) Slog.i(TAG, "positionTaskInStack: removing taskId=" + mTaskId
148 + " from stack=" + mStack);
149 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
150 mStack.removeTask(this);
151 }
152 stack.positionTask(this, position, showForAllUsers());
153 }
154
Craig Mautnerc00204b2013-03-05 15:02:14 -0800155 boolean removeAppToken(AppWindowToken wtoken) {
Craig Mautner42bf39e2014-02-21 16:46:22 -0800156 boolean removed = mAppTokens.remove(wtoken);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800157 if (mAppTokens.size() == 0) {
Wale Ogunwale000957c2015-04-03 08:19:12 -0700158 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId,
Craig Mautner2c2549c2013-11-12 08:31:15 -0800159 "removeAppToken: last token");
Craig Mautnere3119b72015-01-20 15:02:36 -0800160 if (mDeferRemoval) {
161 removeLocked();
162 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800163 }
Craig Mautner83162a92015-01-26 14:43:30 -0800164 wtoken.mTask = null;
165 /* Leave mTaskId for now, it might be useful for debug
166 wtoken.mTaskId = -1;
167 */
Craig Mautner42bf39e2014-02-21 16:46:22 -0800168 return removed;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800169 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800170
Craig Mautnercbd84af2014-10-22 13:21:22 -0700171 void setSendingToBottom(boolean toBottom) {
172 for (int appTokenNdx = 0; appTokenNdx < mAppTokens.size(); appTokenNdx++) {
173 mAppTokens.get(appTokenNdx).sendingToBottom = toBottom;
174 }
175 }
176
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700177 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700178 int setBounds(Rect bounds, Configuration config) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700179 if (config == null) {
180 config = Configuration.EMPTY;
181 }
182 if (bounds == null && !Configuration.EMPTY.equals(config)) {
183 throw new IllegalArgumentException("null bounds but non empty configuration: "
184 + config);
185 }
186 if (bounds != null && Configuration.EMPTY.equals(config)) {
187 throw new IllegalArgumentException("non null bounds, but empty configuration");
188 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700189 boolean oldFullscreen = mFullscreen;
190 int rotation = Surface.ROTATION_0;
191 final DisplayContent displayContent = mStack.getDisplayContent();
192 if (displayContent != null) {
193 displayContent.getLogicalDisplayRect(mTmpRect);
194 rotation = displayContent.getDisplayInfo().rotation;
195 if (bounds == null) {
196 bounds = mTmpRect;
197 mFullscreen = true;
198 } else {
Stefan Kuhne234dbf82015-08-13 09:44:28 -0700199 if (mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID || bounds.isEmpty()) {
200 // ensure bounds are entirely within the display rect
201 if (!bounds.intersect(mTmpRect)) {
202 // Can't set bounds outside the containing display...Sorry!
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700203 return BOUNDS_CHANGE_NONE;
Stefan Kuhne234dbf82015-08-13 09:44:28 -0700204 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700205 }
206 mFullscreen = mTmpRect.equals(bounds);
207 }
208 }
209
210 if (bounds == null) {
211 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700212 return BOUNDS_CHANGE_NONE;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700213 }
214 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700215 return BOUNDS_CHANGE_NONE;
216 }
217
218 int boundsChange = BOUNDS_CHANGE_NONE;
219 if (mBounds.left != bounds.left || mBounds.right != bounds.right) {
220 boundsChange |= BOUNDS_CHANGE_POSITION;
221 }
222 if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
223 boundsChange |= BOUNDS_CHANGE_SIZE;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700224 }
225
226 mBounds.set(bounds);
227 mRotation = rotation;
228 updateDimLayer();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700229 mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700230 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700231 }
232
Chong Zhang87b21722015-09-21 15:39:51 -0700233 boolean resizeLocked(Rect bounds, Configuration configuration, boolean forced) {
Chong Zhang3005e752015-09-18 18:46:28 -0700234 int boundsChanged = setBounds(bounds, configuration);
Chong Zhang87b21722015-09-21 15:39:51 -0700235 if (forced) {
Chong Zhang3005e752015-09-18 18:46:28 -0700236 boundsChanged |= BOUNDS_CHANGE_SIZE;
Chong Zhang3005e752015-09-18 18:46:28 -0700237 }
238 if (boundsChanged == BOUNDS_CHANGE_NONE) {
239 return false;
240 }
241 if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
242 resizeWindows();
243 }
244 return true;
245 }
246
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700247 void getBounds(Rect out) {
248 out.set(mBounds);
249 }
250
Chong Zhang3005e752015-09-18 18:46:28 -0700251 void setDragResizing(boolean dragResizing) {
Chong Zhang3005e752015-09-18 18:46:28 -0700252 mDragResizing = dragResizing;
253 }
254
255 boolean isDragResizing() {
256 return mDragResizing;
257 }
258
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700259 void updateDisplayInfo(final DisplayContent displayContent) {
260 if (displayContent == null) {
261 return;
262 }
263 if (mFullscreen) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700264 setBounds(null, Configuration.EMPTY);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700265 return;
266 }
267 final int newRotation = displayContent.getDisplayInfo().rotation;
268 if (mRotation == newRotation) {
269 return;
270 }
271
272 // Device rotation changed. We don't want the task to move around on the screen when
273 // this happens, so update the task bounds so it stays in the same place.
Wale Ogunwale94744212015-09-21 19:01:47 -0700274 mTmpRect2.set(mBounds);
275 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700276 setBounds(mTmpRect2, mOverrideConfig);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700277 }
278
279 /** Updates the dim layer bounds, recreating it if needed. */
280 private void updateDimLayer() {
281 DimLayer newDimLayer;
282 final boolean previousFullscreen =
283 mDimLayer != null && sSharedFullscreenDimLayers.indexOfValue(mDimLayer) > -1;
284 final int displayId = mStack.getDisplayContent().getDisplayId();
285 if (mFullscreen) {
286 if (previousFullscreen) {
287 // Nothing to do here...
288 return;
289 }
290 // Use shared fullscreen dim layer
291 newDimLayer = sSharedFullscreenDimLayers.get(displayId);
292 if (newDimLayer == null) {
293 if (mDimLayer != null) {
294 // Re-purpose the previous dim layer.
295 newDimLayer = mDimLayer;
296 } else {
297 // Create new full screen dim layer.
298 newDimLayer = new DimLayer(mService, this, displayId);
299 }
300 newDimLayer.setBounds(mBounds);
301 sSharedFullscreenDimLayers.put(displayId, newDimLayer);
302 } else if (mDimLayer != null) {
303 mDimLayer.destroySurface();
304 }
305 } else {
306 newDimLayer = (mDimLayer == null || previousFullscreen)
307 ? new DimLayer(mService, this, displayId) : mDimLayer;
308 newDimLayer.setBounds(mBounds);
309 }
310 mDimLayer = newDimLayer;
311 }
312
313 boolean animateDimLayers() {
314 final int dimLayer;
315 final float dimAmount;
316 if (mDimWinAnimator == null) {
317 dimLayer = mDimLayer.getLayer();
318 dimAmount = 0;
319 } else {
320 dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
321 dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount;
322 }
323 final float targetAlpha = mDimLayer.getTargetAlpha();
324 if (targetAlpha != dimAmount) {
325 if (mDimWinAnimator == null) {
326 mDimLayer.hide(DEFAULT_DIM_DURATION);
327 } else {
328 long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null)
329 ? mDimWinAnimator.mAnimation.computeDurationHint()
330 : DEFAULT_DIM_DURATION;
331 if (targetAlpha > dimAmount) {
332 duration = getDimBehindFadeDuration(duration);
333 }
334 mDimLayer.show(dimLayer, dimAmount, duration);
335 }
336 } else if (mDimLayer.getLayer() != dimLayer) {
337 mDimLayer.setLayer(dimLayer);
338 }
339 if (mDimLayer.isAnimating()) {
340 if (!mService.okToDisplay()) {
341 // Jump to the end of the animation.
342 mDimLayer.show();
343 } else {
344 return mDimLayer.stepAnimation();
345 }
346 }
347 return false;
348 }
349
350 private long getDimBehindFadeDuration(long duration) {
351 TypedValue tv = new TypedValue();
352 mService.mContext.getResources().getValue(
353 com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
354 if (tv.type == TypedValue.TYPE_FRACTION) {
355 duration = (long)tv.getFraction(duration, duration);
356 } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
357 duration = tv.data;
358 }
359 return duration;
360 }
361
362 void clearContinueDimming() {
363 mContinueDimming = false;
364 }
365
366 void setContinueDimming() {
367 mContinueDimming = true;
368 }
369
370 boolean getContinueDimming() {
371 return mContinueDimming;
372 }
373
374 boolean isDimming() {
375 return mDimLayer.isDimming();
376 }
377
378 boolean isDimming(WindowStateAnimator winAnimator) {
379 return mDimWinAnimator == winAnimator && isDimming();
380 }
381
382 void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {
383 // Only set dim params on the highest dimmed layer.
384 // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
385 if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null
386 || !mDimWinAnimator.mSurfaceShown
387 || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
388 mDimWinAnimator = newWinAnimator;
389 if (mDimWinAnimator.mWin.mAppToken == null
390 && !mFullscreen && mStack.getDisplayContent() != null) {
391 // Dim should cover the entire screen for system windows.
392 mStack.getDisplayContent().getLogicalDisplayRect(mTmpRect);
393 mDimLayer.setBounds(mTmpRect);
394 }
395 }
396 }
397
398 void stopDimmingIfNeeded() {
399 if (!mContinueDimming && isDimming()) {
400 mDimWinAnimator = null;
401 mDimLayer.setBounds(mBounds);
402 }
403 }
404
405 void close() {
406 if (mDimLayer != null) {
407 mDimLayer.destroySurface();
408 mDimLayer = null;
409 }
410 }
411
412 void resizeWindows() {
413 final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
414 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
415 final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
416 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
417 final WindowState win = windows.get(winNdx);
418 if (!resizingWindows.contains(win)) {
419 if (DEBUG_RESIZE) Slog.d(TAG, "setBounds: Resizing " + win);
420 resizingWindows.add(win);
421 }
422 }
423 }
424 }
425
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700426 boolean showForAllUsers() {
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700427 final int tokensCount = mAppTokens.size();
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700428 return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700429 }
430
Chong Zhang09b21ef2015-09-14 10:20:21 -0700431 boolean inFreeformWorkspace() {
432 return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
433 }
434
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800435 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700436 public boolean isFullscreen() {
437 return mFullscreen;
438 }
439
440 @Override
441 public DisplayInfo getDisplayInfo() {
442 return mStack.getDisplayContent().getDisplayInfo();
443 }
444
445 @Override
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800446 public String toString() {
Craig Mautner83162a92015-01-26 14:43:30 -0800447 return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800448 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700449
450 public void printTo(String prefix, PrintWriter pw) {
451 pw.print(prefix); pw.print("taskId="); pw.print(mTaskId);
452 pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens);
453 pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval);
454 if (mDimLayer.isDimming()) {
455 pw.print(prefix); pw.println("mDimLayer:");
456 mDimLayer.printTo(prefix + " ", pw);
457 pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
458 } else {
459 pw.println();
460 }
461 }
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800462}