blob: 0e6b1b6a6ce91ab6b576af8cd6c3d998479ad412 [file] [log] [blame]
Winson Chung655332c2016-10-31 13:14:28 -07001/*
2 * Copyright (C) 2016 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
19import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
20import static android.util.TypedValue.COMPLEX_UNIT_DIP;
21
22import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
24
Winson Chunga29eb982016-12-14 12:01:27 -080025import android.app.RemoteAction;
26import android.content.pm.ParceledListSlice;
Winson Chung655332c2016-10-31 13:14:28 -070027import android.content.res.Resources;
28import android.graphics.Point;
Winson Chung84a38342016-11-08 16:15:10 -080029import android.graphics.PointF;
Winson Chung655332c2016-10-31 13:14:28 -070030import android.graphics.Rect;
31import android.os.Handler;
32import android.os.IBinder;
33import android.os.RemoteException;
34import android.util.DisplayMetrics;
35import android.util.Log;
36import android.util.Size;
37import android.util.Slog;
38import android.util.TypedValue;
Winson Chung14fefc22016-11-02 10:02:29 -070039import android.view.DisplayInfo;
Winson Chung655332c2016-10-31 13:14:28 -070040import android.view.Gravity;
41import android.view.IPinnedStackController;
42import android.view.IPinnedStackListener;
43
Winson Chung655332c2016-10-31 13:14:28 -070044import com.android.internal.policy.PipSnapAlgorithm;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070045import com.android.server.UiThread;
Winson Chung655332c2016-10-31 13:14:28 -070046
47import java.io.PrintWriter;
Winson Chunga29eb982016-12-14 12:01:27 -080048import java.util.ArrayList;
49import java.util.List;
Winson Chung655332c2016-10-31 13:14:28 -070050
51/**
Winson Chung2a82fe52017-02-02 14:43:34 -080052 * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever
53 * needs to be restarted, it will be notified with the last known state.
54 *
55 * Changes to the pinned stack also flow through this controller, and generally, the system only
56 * changes the pinned stack bounds through this controller in two ways:
57 *
58 * 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio
59 * and IME state into account.
60 * 2) When rotating the device: the controller calculates the new bounds in the new orientation,
61 * taking the minimized and IME state into account. In this case, we currently ignore the
62 * SystemUI adjustments (ie. expanded for menu, interaction, etc).
63 *
64 * Other changes in the system, including adjustment of IME, configuration change, and more are
65 * handled by SystemUI (similar to the docked stack divider).
Winson Chung655332c2016-10-31 13:14:28 -070066 */
67class PinnedStackController {
68
69 private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;
70
71 private final WindowManagerService mService;
72 private final DisplayContent mDisplayContent;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070073 private final Handler mHandler = UiThread.getHandler();
Winson Chung655332c2016-10-31 13:14:28 -070074
75 private IPinnedStackListener mPinnedStackListener;
76 private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler =
77 new PinnedStackListenerDeathHandler();
78
79 private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback();
80 private final PipSnapAlgorithm mSnapAlgorithm;
Winson Chung655332c2016-10-31 13:14:28 -070081
82 // States that affect how the PIP can be manipulated
Winson Chungfa7053782016-11-08 15:45:10 -080083 private boolean mIsMinimized;
Winson Chung655332c2016-10-31 13:14:28 -070084 private boolean mIsImeShowing;
85 private int mImeHeight;
Winson Chung655332c2016-10-31 13:14:28 -070086
Winson Chung2a82fe52017-02-02 14:43:34 -080087 // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity
Winson Chunga29eb982016-12-14 12:01:27 -080088 private ArrayList<RemoteAction> mActions = new ArrayList<>();
Winson Chung2a82fe52017-02-02 14:43:34 -080089 private float mAspectRatio = -1f;
Winson Chunga29eb982016-12-14 12:01:27 -080090
Winson Chung14fefc22016-11-02 10:02:29 -070091 // Used to calculate stack bounds across rotations
92 private final DisplayInfo mDisplayInfo = new DisplayInfo();
Winson Chung114aeea2017-01-09 16:08:07 -080093 private final Rect mStableInsets = new Rect();
Winson Chung14fefc22016-11-02 10:02:29 -070094
Winson Chung655332c2016-10-31 13:14:28 -070095 // The size and position information that describes where the pinned stack will go by default.
96 private int mDefaultStackGravity;
Mady Mellora7f69742017-02-03 11:00:20 -080097 private float mDefaultAspectRatio;
Winson Chung655332c2016-10-31 13:14:28 -070098 private Point mScreenEdgeInsets;
99
Winson Chung2a82fe52017-02-02 14:43:34 -0800100 // The aspect ratio bounds of the PIP.
101 private float mMinAspectRatio;
102 private float mMaxAspectRatio;
103
Mady Mellora7f69742017-02-03 11:00:20 -0800104 // The minimum edge size of the normal PiP bounds.
105 private int mMinSize;
106
Winson Chung655332c2016-10-31 13:14:28 -0700107 // Temp vars for calculation
108 private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
109 private final Rect mTmpInsets = new Rect();
Jorim Jaggiad5d2842016-11-01 18:22:53 -0700110 private final Rect mTmpRect = new Rect();
Winson Chung34a07f42017-03-10 18:06:25 -0800111 private final Rect mTmpAnimatingBoundsRect = new Rect();
Winson Chungf1f72f62017-02-14 17:15:48 -0800112 private final Point mTmpDisplaySize = new Point();
Winson Chung655332c2016-10-31 13:14:28 -0700113
114 /**
115 * The callback object passed to listeners for them to notify the controller of state changes.
116 */
117 private class PinnedStackControllerCallback extends IPinnedStackController.Stub {
118
119 @Override
Winson Chungfa7053782016-11-08 15:45:10 -0800120 public void setIsMinimized(final boolean isMinimized) {
121 mHandler.post(() -> {
122 mIsMinimized = isMinimized;
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800123 mSnapAlgorithm.setMinimized(isMinimized);
Winson Chungfa7053782016-11-08 15:45:10 -0800124 });
125 }
Winson Chung655332c2016-10-31 13:14:28 -0700126 }
127
128 /**
129 * Handler for the case where the listener dies.
130 */
131 private class PinnedStackListenerDeathHandler implements IBinder.DeathRecipient {
132
133 @Override
134 public void binderDied() {
135 // Clean up the state if the listener dies
Winson Chung655332c2016-10-31 13:14:28 -0700136 mPinnedStackListener = null;
137 }
138 }
139
140 PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
141 mService = service;
142 mDisplayContent = displayContent;
143 mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
Winson Chung14fefc22016-11-02 10:02:29 -0700144 mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
Winson Chung655332c2016-10-31 13:14:28 -0700145 reloadResources();
146 }
147
148 void onConfigurationChanged() {
149 reloadResources();
Winson Chung2a82fe52017-02-02 14:43:34 -0800150 notifyMovementBoundsChanged(false /* fromImeAdjustment */);
Winson Chung655332c2016-10-31 13:14:28 -0700151 }
152
153 /**
154 * Reloads all the resources for the current configuration.
155 */
156 void reloadResources() {
157 final Resources res = mService.mContext.getResources();
Mady Mellora7f69742017-02-03 11:00:20 -0800158 mMinSize = res.getDimensionPixelSize(
159 com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
160 mDefaultAspectRatio = res.getFloat(
161 com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
Winson Chung655332c2016-10-31 13:14:28 -0700162 final Size screenEdgeInsetsDp = Size.parseSize(res.getString(
163 com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets));
164 mDefaultStackGravity = res.getInteger(
165 com.android.internal.R.integer.config_defaultPictureInPictureGravity);
166 mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
Winson Chung655332c2016-10-31 13:14:28 -0700167 mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
168 dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
Winson Chung2a82fe52017-02-02 14:43:34 -0800169 mMinAspectRatio = res.getFloat(
170 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
171 mMaxAspectRatio = res.getFloat(
172 com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
Winson Chung655332c2016-10-31 13:14:28 -0700173 }
174
175 /**
176 * Registers a pinned stack listener.
177 */
178 void registerPinnedStackListener(IPinnedStackListener listener) {
179 try {
180 listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
181 listener.onListenerRegistered(mCallbacks);
182 mPinnedStackListener = listener;
Winson Chung2a82fe52017-02-02 14:43:34 -0800183 notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
184 // The movement bounds notification needs to be sent before the minimized state, since
185 // SystemUI may use the bounds to retore the minimized position
186 notifyMovementBoundsChanged(false /* fromImeAdjustment */);
Winson Chunga29eb982016-12-14 12:01:27 -0800187 notifyActionsChanged(mActions);
Winson Chung2a82fe52017-02-02 14:43:34 -0800188 notifyMinimizeChanged(mIsMinimized);
Winson Chung655332c2016-10-31 13:14:28 -0700189 } catch (RemoteException e) {
190 Log.e(TAG, "Failed to register pinned stack listener", e);
191 }
192 }
193
194 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800195 * @return whether the given {@param aspectRatio} is valid.
196 */
197 public boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
198 return mMinAspectRatio <= aspectRatio && aspectRatio <= mMaxAspectRatio;
199 }
200
201 /**
Winson Chung84a38342016-11-08 16:15:10 -0800202 * Returns the current bounds (or the default bounds if there are no current bounds) with the
203 * specified aspect ratio.
204 */
Winson Chung2a82fe52017-02-02 14:43:34 -0800205 Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) {
Mady Mellora7f69742017-02-03 11:00:20 -0800206 // Save the snap fraction, calculate the aspect ratio based on screen size
Winson Chung84a38342016-11-08 16:15:10 -0800207 final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
208 getMovementBounds(stackBounds));
Mady Mellora7f69742017-02-03 11:00:20 -0800209 final Size size = getSize(aspectRatio);
210 final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
211 final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
212 stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
Winson Chung84a38342016-11-08 16:15:10 -0800213 mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
Winson Chungf1f72f62017-02-14 17:15:48 -0800214 if (mIsMinimized) {
215 applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds));
216 }
Winson Chung84a38342016-11-08 16:15:10 -0800217 return stackBounds;
218 }
219
220 /**
Mady Mellora7f69742017-02-03 11:00:20 -0800221 * @return the size of the PIP based on the given {@param aspectRatio}.
222 */
223 Size getSize(float aspectRatio) {
224 return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
225 mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
226 }
227
228 /**
Winson Chung655332c2016-10-31 13:14:28 -0700229 * @return the default bounds to show the PIP when there is no active PIP.
230 */
231 Rect getDefaultBounds() {
Winson Chung655332c2016-10-31 13:14:28 -0700232 final Rect insetBounds = new Rect();
Winson Chung14fefc22016-11-02 10:02:29 -0700233 getInsetBounds(insetBounds);
Winson Chung655332c2016-10-31 13:14:28 -0700234
235 final Rect defaultBounds = new Rect();
Mady Mellora7f69742017-02-03 11:00:20 -0800236 final Size size = getSize(mDefaultAspectRatio);
Winson Chungbaa7b722017-03-03 21:33:44 -0800237 Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
238 0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
Winson Chung655332c2016-10-31 13:14:28 -0700239 return defaultBounds;
240 }
241
242 /**
Winson Chung47f2bf62017-02-16 18:58:12 -0800243 * Updates the display info, calculating and returning the new stack and movement bounds in the
244 * new orientation of the device if necessary.
Winson Chung655332c2016-10-31 13:14:28 -0700245 */
Winson Chung47f2bf62017-02-16 18:58:12 -0800246 void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
247 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
248 if (mDisplayInfo.equals(displayInfo)) {
249 return;
Winson Chung14fefc22016-11-02 10:02:29 -0700250 }
Winson Chung47f2bf62017-02-16 18:58:12 -0800251
252 mTmpRect.set(targetBounds);
253 final Rect postChangeStackBounds = mTmpRect;
254
255 // Calculate the snap fraction of the current stack along the old movement bounds
256 final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
257 final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
258 preChangeMovementBounds);
259 mDisplayInfo.copyFrom(displayInfo);
260
261 // Calculate the stack bounds in the new orientation to the same same fraction along the
262 // rotated movement bounds.
263 final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
264 false /* adjustForIme */);
265 mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
266 snapFraction);
267 if (mIsMinimized) {
268 applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
269 }
270
271 notifyMovementBoundsChanged(false /* fromImeAdjustment */);
272
273 outBounds.set(postChangeStackBounds);
Winson Chung655332c2016-10-31 13:14:28 -0700274 }
275
276 /**
277 * Sets the Ime state and height.
278 */
279 void setAdjustedForIme(boolean adjustedForIme, int imeHeight) {
280 // Return early if there is no state change
281 if (mIsImeShowing == adjustedForIme && mImeHeight == imeHeight) {
282 return;
283 }
284
Winson Chung655332c2016-10-31 13:14:28 -0700285 mIsImeShowing = adjustedForIme;
286 mImeHeight = imeHeight;
Winson Chung2a82fe52017-02-02 14:43:34 -0800287 notifyImeVisibilityChanged(adjustedForIme, imeHeight);
288 notifyMovementBoundsChanged(true /* fromImeAdjustment */);
289 }
290
291 /**
292 * Sets the current aspect ratio.
293 */
294 void setAspectRatio(float aspectRatio) {
295 if (Float.compare(mAspectRatio, aspectRatio) != 0) {
296 mAspectRatio = aspectRatio;
297 notifyMovementBoundsChanged(false /* fromImeAdjustment */);
Winson Chung655332c2016-10-31 13:14:28 -0700298 }
299 }
300
301 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800302 * Sets the current set of actions.
303 */
304 void setActions(List<RemoteAction> actions) {
305 mActions.clear();
Winson Chungc2baac02017-01-11 13:34:47 -0800306 if (actions != null) {
307 mActions.addAll(actions);
308 }
Winson Chunga29eb982016-12-14 12:01:27 -0800309 notifyActionsChanged(mActions);
310 }
311
312 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800313 * Notifies listeners that the PIP needs to be adjusted for the IME.
Winson Chung655332c2016-10-31 13:14:28 -0700314 */
Winson Chung2a82fe52017-02-02 14:43:34 -0800315 private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) {
Winson Chung655332c2016-10-31 13:14:28 -0700316 if (mPinnedStackListener != null) {
317 try {
Winson Chung2a82fe52017-02-02 14:43:34 -0800318 mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight);
Winson Chung655332c2016-10-31 13:14:28 -0700319 } catch (RemoteException e) {
320 Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
321 }
322 }
323 }
324
325 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800326 * Notifies listeners that the PIP minimized state has changed.
327 */
328 private void notifyMinimizeChanged(boolean isMinimized) {
329 if (mPinnedStackListener != null) {
330 try {
331 mPinnedStackListener.onMinimizedStateChanged(isMinimized);
332 } catch (RemoteException e) {
333 Slog.e(TAG_WM, "Error delivering minimize changed event.", e);
334 }
335 }
336 }
337
338 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800339 * Notifies listeners that the PIP actions have changed.
340 */
341 private void notifyActionsChanged(List<RemoteAction> actions) {
342 if (mPinnedStackListener != null) {
343 try {
344 mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions));
345 } catch (RemoteException e) {
346 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
347 }
348 }
349 }
350
351 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800352 * Notifies listeners that the PIP movement bounds have changed.
353 */
354 private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
355 if (mPinnedStackListener != null) {
356 try {
Winson Chungbaa7b722017-03-03 21:33:44 -0800357 final Rect insetBounds = new Rect();
Winson Chung2a82fe52017-02-02 14:43:34 -0800358 getInsetBounds(insetBounds);
Winson Chungbaa7b722017-03-03 21:33:44 -0800359 final Rect normalBounds = getDefaultBounds();
Winson Chung2a82fe52017-02-02 14:43:34 -0800360 if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
361 transformBoundsToAspectRatio(normalBounds, mAspectRatio);
362 }
Winson Chung34a07f42017-03-10 18:06:25 -0800363 final Rect animatingBounds = mTmpAnimatingBoundsRect;
Winson Chungbaa7b722017-03-03 21:33:44 -0800364 final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
365 if (pinnedStack != null) {
366 pinnedStack.getAnimatingBounds(animatingBounds);
367 } else {
368 animatingBounds.set(normalBounds);
369 }
Winson Chung2a82fe52017-02-02 14:43:34 -0800370 mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
Winson Chungbaa7b722017-03-03 21:33:44 -0800371 animatingBounds, fromImeAdjustement);
Winson Chung2a82fe52017-02-02 14:43:34 -0800372 } catch (RemoteException e) {
373 Slog.e(TAG_WM, "Error delivering actions changed event.", e);
374 }
375 }
376 }
377
378 /**
Winson Chung655332c2016-10-31 13:14:28 -0700379 * @return the bounds on the screen that the PIP can be visible in.
380 */
Winson Chung14fefc22016-11-02 10:02:29 -0700381 private void getInsetBounds(Rect outRect) {
382 mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
383 mDisplayInfo.logicalHeight, mTmpInsets);
384 outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
385 mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
386 mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
Winson Chung655332c2016-10-31 13:14:28 -0700387 }
388
389 /**
Winson Chung55893332017-02-17 17:13:10 -0800390 * @return the movement bounds for the given {@param stackBounds} and the current state of the
391 * controller.
392 */
393 private Rect getMovementBounds(Rect stackBounds) {
394 return getMovementBounds(stackBounds, true /* adjustForIme */);
395 }
396
397 /**
398 * @return the movement bounds for the given {@param stackBounds} and the current state of the
399 * controller.
400 */
401 private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
402 final Rect movementBounds = new Rect();
403 getInsetBounds(movementBounds);
404
405 // Apply the movement bounds adjustments based on the current state
406 mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
407 (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
408 return movementBounds;
409 }
410
411 /**
Winson Chungf1f72f62017-02-14 17:15:48 -0800412 * Applies the minimized offsets to the given stack bounds.
413 */
414 private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
415 mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
416 mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
417 mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
418 mStableInsets);
419 }
420
421 /**
Winson Chung655332c2016-10-31 13:14:28 -0700422 * @return the pixels for a given dp value.
423 */
424 private int dpToPx(float dpValue, DisplayMetrics dm) {
425 return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
426 }
427
428 void dump(String prefix, PrintWriter pw) {
429 pw.println(prefix + "PinnedStackController");
Jorim Jaggiad5d2842016-11-01 18:22:53 -0700430 pw.print(prefix + " defaultBounds="); getDefaultBounds().printShortString(pw);
431 pw.println();
432 mService.getStackBounds(PINNED_STACK_ID, mTmpRect);
433 pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
434 pw.println();
Winson Chung655332c2016-10-31 13:14:28 -0700435 pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
Winson Chungfa7053782016-11-08 15:45:10 -0800436 pw.println(prefix + " mIsMinimized=" + mIsMinimized);
Winson Chunga29eb982016-12-14 12:01:27 -0800437 if (mActions.isEmpty()) {
438 pw.println(prefix + " mActions=[]");
439 } else {
440 pw.println(prefix + " mActions=[");
441 for (int i = 0; i < mActions.size(); i++) {
442 RemoteAction action = mActions.get(i);
443 pw.print(prefix + " Action[" + i + "]: ");
444 action.dump("", pw);
445 }
446 pw.println(prefix + " ]");
447 }
Winson Chung655332c2016-10-31 13:14:28 -0700448 }
449}