blob: 33e46f4af301edb96bbb046017e517fe3296e03b [file] [log] [blame]
Jeff Brown4ccb8232014-01-16 22:16:42 -08001/*
Adrian Roose99bc052017-11-20 17:55:31 +01002 * Copyright (C) 2017 The Android Open Source Project
Jeff Brown4ccb8232014-01-16 22:16:42 -08003 *
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
Adrian Roose99bc052017-11-20 17:55:31 +010017package com.android.server.wm;
Jeff Brown4ccb8232014-01-16 22:16:42 -080018
Alan Viverette59e53a12016-03-28 13:41:32 -040019import android.annotation.NonNull;
Alan Viverette214fb682015-11-17 09:47:11 -050020import android.annotation.Nullable;
Daichi Hirono3c6c95e2017-09-13 12:23:57 +090021import android.content.ClipData;
Svetoslav8e3feb12014-02-24 13:46:47 -080022import android.graphics.Rect;
23import android.graphics.Region;
Jeff Brown4ccb8232014-01-16 22:16:42 -080024import android.hardware.display.DisplayManagerInternal;
Svetoslav8e3feb12014-02-24 13:46:47 -080025import android.os.IBinder;
Daichi Hirono4a545172018-02-01 10:59:48 +090026import android.view.Display;
Adrian Roose99bc052017-11-20 17:55:31 +010027import android.view.IInputFilter;
28import android.view.IWindow;
Daichi Hirono4a545172018-02-01 10:59:48 +090029import android.view.InputChannel;
Adrian Roose99bc052017-11-20 17:55:31 +010030import android.view.MagnificationSpec;
31import android.view.WindowInfo;
Svetoslav8e3feb12014-02-24 13:46:47 -080032
Daichi Hirono4a545172018-02-01 10:59:48 +090033import com.android.server.input.InputManagerService;
Adrian Roose99bc052017-11-20 17:55:31 +010034import com.android.server.policy.WindowManagerPolicy;
35
Svetoslav8e3feb12014-02-24 13:46:47 -080036import java.util.List;
Jeff Brown4ccb8232014-01-16 22:16:42 -080037
38/**
39 * Window manager local system service interface.
40 *
41 * @hide Only for use within the system server.
42 */
43public abstract class WindowManagerInternal {
Svetoslav8e3feb12014-02-24 13:46:47 -080044
45 /**
46 * Interface to receive a callback when the windows reported for
47 * accessibility changed.
48 */
49 public interface WindowsForAccessibilityCallback {
50
51 /**
52 * Called when the windows for accessibility changed.
53 *
54 * @param windows The windows for accessibility.
55 */
56 public void onWindowsForAccessibilityChanged(List<WindowInfo> windows);
57 }
58
59 /**
60 * Callbacks for contextual changes that affect the screen magnification
61 * feature.
62 */
63 public interface MagnificationCallbacks {
64
65 /**
Phil Weaver70439242016-03-10 15:15:49 -080066 * Called when the region where magnification operates changes. Note that this isn't the
67 * entire screen. For example, IMEs are not magnified.
Svetoslav8e3feb12014-02-24 13:46:47 -080068 *
Phil Weaver70439242016-03-10 15:15:49 -080069 * @param magnificationRegion the current magnification region
Svetoslav8e3feb12014-02-24 13:46:47 -080070 */
Phil Weaver70439242016-03-10 15:15:49 -080071 public void onMagnificationRegionChanged(Region magnificationRegion);
Svetoslav8e3feb12014-02-24 13:46:47 -080072
73 /**
74 * Called when an application requests a rectangle on the screen to allow
75 * the client to apply the appropriate pan and scale.
76 *
77 * @param left The rectangle left.
78 * @param top The rectangle top.
79 * @param right The rectangle right.
80 * @param bottom The rectangle bottom.
81 */
82 public void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
83
84 /**
85 * Notifies that the rotation changed.
86 *
87 * @param rotation The current rotation.
88 */
89 public void onRotationChanged(int rotation);
90
91 /**
92 * Notifies that the context of the user changed. For example, an application
93 * was started.
94 */
95 public void onUserContextChanged();
96 }
97
Jeff Brown4ccb8232014-01-16 22:16:42 -080098 /**
Jorim Jaggi77ba4802015-02-18 13:57:50 +010099 * Abstract class to be notified about {@link com.android.server.wm.AppTransition} events. Held
100 * as an abstract class so a listener only needs to implement the methods of its interest.
101 */
102 public static abstract class AppTransitionListener {
103
104 /**
105 * Called when an app transition is being setup and about to be executed.
106 */
107 public void onAppTransitionPendingLocked() {}
108
109 /**
110 * Called when a pending app transition gets cancelled.
Jorim Jaggife762342016-10-13 14:33:27 +0200111 *
112 * @param transit transition type indicating what kind of transition got cancelled
Jorim Jaggi77ba4802015-02-18 13:57:50 +0100113 */
Jorim Jaggife762342016-10-13 14:33:27 +0200114 public void onAppTransitionCancelledLocked(int transit) {}
Jorim Jaggi77ba4802015-02-18 13:57:50 +0100115
116 /**
117 * Called when an app transition gets started
118 *
Jorim Jaggife762342016-10-13 14:33:27 +0200119 * @param transit transition type indicating what kind of transition gets run, must be one
120 * of AppTransition.TRANSIT_* values
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200121 * @param duration the total duration of the transition
122 * @param statusBarAnimationStartTime the desired start time for all visual animations in
123 * the status bar caused by this app transition in uptime millis
124 * @param statusBarAnimationDuration the duration for all visual animations in the status
125 * bar caused by this app transition in millis
Jorim Jaggife762342016-10-13 14:33:27 +0200126 *
127 * @return Return any bit set of {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
128 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
129 * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER},
130 * or {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
Jorim Jaggi77ba4802015-02-18 13:57:50 +0100131 */
Evan Rosky2289ba12018-11-19 18:28:18 -0800132 public int onAppTransitionStartingLocked(int transit, long duration,
133 long statusBarAnimationStartTime, long statusBarAnimationDuration) {
Jorim Jaggife762342016-10-13 14:33:27 +0200134 return 0;
135 }
Jorim Jaggi77ba4802015-02-18 13:57:50 +0100136
137 /**
138 * Called when an app transition is finished running.
139 *
140 * @param token the token for app whose transition has finished
141 */
142 public void onAppTransitionFinishedLocked(IBinder token) {}
143 }
144
145 /**
Seigo Nonaka7309b122015-08-17 18:34:13 -0700146 * An interface to be notified about hardware keyboard status.
147 */
148 public interface OnHardKeyboardStatusChangeListener {
149 public void onHardKeyboardStatusChange(boolean available);
150 }
151
152 /**
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900153 * An interface to customize drag and drop behaviors.
154 */
155 public interface IDragDropCallback {
Daichi Hirono4a545172018-02-01 10:59:48 +0900156 default boolean registerInputChannel(
157 DragState state, Display display, InputManagerService service,
158 InputChannel source) {
chaviwb5e316c2018-12-26 15:39:15 -0800159 state.mTransferTouchFromToken = source.getToken();
Daichi Hirono4a545172018-02-01 10:59:48 +0900160 state.register(display);
chaviwb5e316c2018-12-26 15:39:15 -0800161 return true;
Daichi Hirono4a545172018-02-01 10:59:48 +0900162 }
163
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900164 /**
Daichi Hironobb28efb2017-11-21 15:11:01 +0900165 * Called when drag operation is starting.
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900166 */
Daichi Hironobb28efb2017-11-21 15:11:01 +0900167 default boolean prePerformDrag(IWindow window, IBinder dragToken,
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900168 int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
169 ClipData data) {
170 return true;
171 }
172
173 /**
Daichi Hironobb28efb2017-11-21 15:11:01 +0900174 * Called when drag operation is started.
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900175 */
Daichi Hironobb28efb2017-11-21 15:11:01 +0900176 default void postPerformDrag() {}
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900177
178 /**
Daichi Hironobb28efb2017-11-21 15:11:01 +0900179 * Called when drop result is being reported.
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900180 */
Daichi Hironobb28efb2017-11-21 15:11:01 +0900181 default void preReportDropResult(IWindow window, boolean consumed) {}
182
183 /**
184 * Called when drop result was reported.
185 */
186 default void postReportDropResult() {}
187
188 /**
189 * Called when drag operation is being cancelled.
190 */
191 default void preCancelDragAndDrop(IBinder dragToken) {}
192
193 /**
194 * Called when drag operation was cancelled.
195 */
196 default void postCancelDragAndDrop() {}
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900197 }
198
199 /**
Jeff Brown4ccb8232014-01-16 22:16:42 -0800200 * Request that the window manager call
201 * {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager}
202 * within a surface transaction at a later time.
203 */
204 public abstract void requestTraversalFromDisplayManager();
Svetoslav8e3feb12014-02-24 13:46:47 -0800205
206 /**
207 * Set by the accessibility layer to observe changes in the magnified region,
208 * rotation, and other window transformations related to display magnification
209 * as the window manager is responsible for doing the actual magnification
210 * and has access to the raw window data while the accessibility layer serves
211 * as a controller.
212 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800213 * @param displayId The logical display id.
Svetoslav8e3feb12014-02-24 13:46:47 -0800214 * @param callbacks The callbacks to invoke.
Rhed Jao02655dc2018-10-30 20:44:52 +0800215 * @return {@code false} if display id is not valid.
Svetoslav8e3feb12014-02-24 13:46:47 -0800216 */
Rhed Jao02655dc2018-10-30 20:44:52 +0800217 public abstract boolean setMagnificationCallbacks(int displayId,
218 @Nullable MagnificationCallbacks callbacks);
Svetoslav8e3feb12014-02-24 13:46:47 -0800219
220 /**
221 * Set by the accessibility layer to specify the magnification and panning to
222 * be applied to all windows that should be magnified.
223 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800224 * @param displayId The logical display id.
Craig Mautner8a0da012014-05-31 15:13:37 -0700225 * @param spec The MagnficationSpec to set.
Svetoslav8e3feb12014-02-24 13:46:47 -0800226 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800227 * @see #setMagnificationCallbacks(int, MagnificationCallbacks)
Svetoslav8e3feb12014-02-24 13:46:47 -0800228 */
Rhed Jao02655dc2018-10-30 20:44:52 +0800229 public abstract void setMagnificationSpec(int displayId, MagnificationSpec spec);
Svetoslav8e3feb12014-02-24 13:46:47 -0800230
231 /**
Casey Burkhardt74922c62017-02-13 12:43:16 -0800232 * Set by the accessibility framework to indicate whether the magnifiable regions of the display
233 * should be shown.
234 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800235 * @param displayId The logical display id.
Casey Burkhardt74922c62017-02-13 12:43:16 -0800236 * @param show {@code true} to show magnifiable region bounds, {@code false} to hide
237 */
Rhed Jao02655dc2018-10-30 20:44:52 +0800238 public abstract void setForceShowMagnifiableBounds(int displayId, boolean show);
Casey Burkhardt74922c62017-02-13 12:43:16 -0800239
240 /**
Phil Weaver70439242016-03-10 15:15:49 -0800241 * Obtains the magnification regions.
Alan Viverette59e53a12016-03-28 13:41:32 -0400242 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800243 * @param displayId The logical display id.
Phil Weaver70439242016-03-10 15:15:49 -0800244 * @param magnificationRegion the current magnification region
Alan Viverette59e53a12016-03-28 13:41:32 -0400245 */
Rhed Jao02655dc2018-10-30 20:44:52 +0800246 public abstract void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion);
Alan Viverette59e53a12016-03-28 13:41:32 -0400247
248 /**
Svetoslav8e3feb12014-02-24 13:46:47 -0800249 * Gets the magnification and translation applied to a window given its token.
250 * Not all windows are magnified and the window manager policy determines which
251 * windows are magnified. The returned result also takes into account the compat
252 * scale if necessary.
253 *
254 * @param windowToken The window's token.
255 *
256 * @return The magnification spec for the window.
257 *
Rhed Jao02655dc2018-10-30 20:44:52 +0800258 * @see #setMagnificationCallbacks(int, MagnificationCallbacks)
Svetoslav8e3feb12014-02-24 13:46:47 -0800259 */
260 public abstract MagnificationSpec getCompatibleMagnificationSpecForWindow(
261 IBinder windowToken);
262
263 /**
264 * Sets a callback for observing which windows are touchable for the purposes
265 * of accessibility.
266 *
267 * @param callback The callback.
268 */
269 public abstract void setWindowsForAccessibilityCallback(
270 WindowsForAccessibilityCallback callback);
271
272 /**
273 * Sets a filter for manipulating the input event stream.
274 *
275 * @param filter The filter implementation.
276 */
277 public abstract void setInputFilter(IInputFilter filter);
278
279 /**
280 * Gets the token of the window that has input focus.
281 *
282 * @return The token.
283 */
284 public abstract IBinder getFocusedWindowToken();
285
286 /**
287 * @return Whether the keyguard is engaged.
288 */
289 public abstract boolean isKeyguardLocked();
290
291 /**
Jonathan Solnit6e8d7092017-06-15 15:17:20 -0700292 * @return Whether the keyguard is showing and not occluded.
293 */
294 public abstract boolean isKeyguardShowingAndNotOccluded();
295
296 /**
Svetoslav8e3feb12014-02-24 13:46:47 -0800297 * Gets the frame of a window given its token.
298 *
299 * @param token The token.
300 * @param outBounds The frame to populate.
301 */
302 public abstract void getWindowFrame(IBinder token, Rect outBounds);
Craig Mautner8a0da012014-05-31 15:13:37 -0700303
304 /**
Alan Viverettee34560b22014-07-10 14:50:06 -0700305 * Opens the global actions dialog.
306 */
307 public abstract void showGlobalActions();
308
309 /**
Craig Mautner8a0da012014-05-31 15:13:37 -0700310 * Invalidate all visible windows. Then report back on the callback once all windows have
311 * redrawn.
312 */
Craig Mautner13f6ea72014-06-23 14:57:02 -0700313 public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout);
Svetoslav3a5c7212014-10-14 09:54:26 -0700314
315 /**
Adrian Roos595416b2018-10-14 14:50:33 +0200316 * Overrides the display size.
317 *
318 * @param displayId The display to override the display size.
319 * @param width The width to override.
320 * @param height The height to override.
321 */
322 public abstract void setForcedDisplaySize(int displayId, int width, int height);
323
324 /**
325 * Recover the display size to real display size.
326 *
327 * @param displayId The display to recover the display size.
328 */
329 public abstract void clearForcedDisplaySize(int displayId);
330
331 /**
Svetoslav3a5c7212014-10-14 09:54:26 -0700332 * Adds a window token for a given window type.
333 *
334 * @param token The token to add.
335 * @param type The window type.
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700336 * @param displayId The display to add the token to.
Svetoslav3a5c7212014-10-14 09:54:26 -0700337 */
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700338 public abstract void addWindowToken(android.os.IBinder token, int type, int displayId);
Svetoslav3a5c7212014-10-14 09:54:26 -0700339
340 /**
341 * Removes a window token.
342 *
343 * @param token The toke to remove.
344 * @param removeWindows Whether to also remove the windows associated with the token.
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700345 * @param displayId The display to remove the token from.
Svetoslav3a5c7212014-10-14 09:54:26 -0700346 */
Wale Ogunwaleac2561e2016-11-01 15:43:46 -0700347 public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows,
348 int displayId);
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100349
350 /**
351 * Registers a listener to be notified about app transition events.
352 *
353 * @param listener The listener to register.
354 */
355 public abstract void registerAppTransitionListener(AppTransitionListener listener);
Seigo Nonaka7309b122015-08-17 18:34:13 -0700356
357 /**
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100358 * Reports that the password for the given user has changed.
359 */
360 public abstract void reportPasswordChanged(int userId);
361
362 /**
lumark90120a82018-08-15 00:33:03 +0800363 * Retrieves a height of input method window for given display.
Seigo Nonaka7309b122015-08-17 18:34:13 -0700364 */
lumark90120a82018-08-15 00:33:03 +0800365 public abstract int getInputMethodWindowVisibleHeight(int displayId);
Seigo Nonaka7309b122015-08-17 18:34:13 -0700366
367 /**
Yohei Yukawa69e68022017-02-13 12:04:50 -0800368 * Notifies WindowManagerService that the current IME window status is being changed.
369 *
Yohei Yukawa603f4d02018-09-11 15:04:58 -0700370 * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
371 * tested caller of this method.</p>
Yohei Yukawa69e68022017-02-13 12:04:50 -0800372 *
373 * @param imeToken token to track the active input method. Corresponding IME windows can be
374 * identified by checking {@link android.view.WindowManager.LayoutParams#token}.
375 * Note that there is no guarantee that the corresponding window is already
376 * created
377 * @param imeWindowVisible whether the active IME thinks that its window should be visible or
378 * hidden, no matter how WindowManagerService will react / has reacted
379 * to corresponding API calls. Note that this state is not guaranteed
380 * to be synchronized with state in WindowManagerService.
Yohei Yukawad6475a62017-04-17 10:35:27 -0700381 * @param dismissImeOnBackKeyPressed {@code true} if the software keyboard is shown and the back
382 * key is expected to dismiss the software keyboard.
Yohei Yukawa69e68022017-02-13 12:04:50 -0800383 */
Yohei Yukawaee2a7ed2017-02-15 21:38:57 -0800384 public abstract void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
Yohei Yukawa99e1f6e2018-06-22 17:33:19 -0700385 boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed);
386
387 /**
388 * Notifies WindowManagerService that the current IME window status is being changed.
389 *
Yohei Yukawa603f4d02018-09-11 15:04:58 -0700390 * <p>Only {@link com.android.server.inputmethod.InputMethodManagerService} is the expected and
391 * tested caller of this method.</p>
Yohei Yukawa99e1f6e2018-06-22 17:33:19 -0700392 *
393 * @param imeToken token to track the active input method. Corresponding IME windows can be
394 * identified by checking {@link android.view.WindowManager.LayoutParams#token}.
395 * Note that there is no guarantee that the corresponding window is already
396 * created
397 * @param imeTargetWindowToken token to identify the target window that the IME is associated
398 * with
399 */
400 public abstract void updateInputMethodTargetWindow(@NonNull IBinder imeToken,
401 @NonNull IBinder imeTargetWindowToken);
Yohei Yukawa69e68022017-02-13 12:04:50 -0800402
403 /**
Seigo Nonaka7309b122015-08-17 18:34:13 -0700404 * Returns true when the hardware keyboard is available.
405 */
406 public abstract boolean isHardKeyboardAvailable();
407
408 /**
409 * Sets the callback listener for hardware keyboard status changes.
410 *
411 * @param listener The listener to set.
412 */
413 public abstract void setOnHardKeyboardStatusChangeListener(
414 OnHardKeyboardStatusChangeListener listener);
Wale Ogunwale6e94a9e2015-10-07 15:35:49 -0700415
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700416 /** Returns true if a stack in the windowing mode is currently visible. */
417 public abstract boolean isStackVisible(int windowingMode);
Jorim Jaggi9511b0f2016-01-29 19:12:44 -0800418
419 /**
Phil Weaverc72faad2018-07-24 10:53:01 -0700420 * Requests the window manager to resend the windows for accessibility.
Svetoslav Ganovfd138892016-07-13 18:20:42 -0700421 */
422 public abstract void computeWindowsForAccessibility();
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700423
424 /**
425 * Called after virtual display Id is updated by
426 * {@link com.android.server.vr.Vr2dDisplay} with a specific
427 * {@param vr2dDisplayId}.
428 */
429 public abstract void setVr2dDisplayId(int vr2dDisplayId);
Daichi Hirono3c6c95e2017-09-13 12:23:57 +0900430
431 /**
432 * Sets callback to DragDropController.
433 */
434 public abstract void registerDragDropControllerCallback(IDragDropCallback callback);
Eugene Suslaf9a651d2017-10-11 12:06:27 -0700435
436 /**
437 * @see android.view.IWindowManager#lockNow
438 */
439 public abstract void lockNow();
Tony Mak6f2e97e2018-03-26 20:43:06 +0100440
441 /**
442 * Return the user that owns the given window, {@link android.os.UserHandle#USER_NULL} if
443 * the window token is not found.
444 */
445 public abstract int getWindowOwnerUserId(IBinder windowToken);
Chad Brubakera6b2d5c2018-06-25 12:50:01 -0700446
447 /**
448 * Returns {@code true} if a Window owned by {@code uid} has focus.
449 */
450 public abstract boolean isUidFocused(int uid);
Yohei Yukawacf93f9a2018-08-30 15:58:47 -0700451
452 /**
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800453 * Checks whether the specified IME client has IME focus or not.
Yohei Yukawa41f89c32018-09-19 14:30:04 -0700454 *
455 * @param uid UID of the process to be queried
456 * @param pid PID of the process to be queried
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800457 * @param displayId Display ID reported from the client. Note that this method also verifies
458 * whether the specified process is allowed to access to this display or not
459 * @return {@code true} if the IME client specified with {@code uid}, {@code pid}, and
460 * {@code displayId} has IME focus
Yohei Yukawacf93f9a2018-08-30 15:58:47 -0700461 */
Yohei Yukawa4052a10f2018-10-15 15:35:55 +0800462 public abstract boolean isInputMethodClientFocus(int uid, int pid, int displayId);
463
464 /**
465 * Checks whether the given {@code uid} is allowed to use the given {@code displayId} or not.
466 *
467 * @param displayId Display ID to be checked
468 * @param uid UID to be checked.
469 * @return {@code true} if the given {@code uid} is allowed to use the given {@code displayId}
470 */
471 public abstract boolean isUidAllowedOnDisplay(int displayId, int uid);
lumark90120a82018-08-15 00:33:03 +0800472
473 /**
474 * Return the display Id for given window.
475 */
476 public abstract int getDisplayIdForWindow(IBinder windowToken);
Svetoslav8e3feb12014-02-24 13:46:47 -0800477}