blob: 24c372cef7cb7ba5d974ae341a85d12423d5d945 [file] [log] [blame]
Jason Monkb5b092012017-01-05 11:35:34 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.statusbar;
16
Charles Chen24e7a9f2018-11-21 11:59:07 +080017import static android.view.Display.DEFAULT_DISPLAY;
Tiger Huang332793b2019-10-29 23:21:27 +080018import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
19import static android.view.InsetsState.ITYPE_STATUS_BAR;
Charles Chen24e7a9f2018-11-21 11:59:07 +080020
Charles Chenf3d295c2018-11-30 18:15:21 +080021import static org.mockito.ArgumentMatchers.anyInt;
Jason Monkb5b092012017-01-05 11:35:34 -050022import static org.mockito.Matchers.eq;
23import static org.mockito.Mockito.mock;
24import static org.mockito.Mockito.verify;
25import static org.mockito.Mockito.verifyNoMoreInteractions;
26
27import android.content.ComponentName;
28import android.graphics.Rect;
29import android.os.Bundle;
Jorim Jaggi956ca412019-01-07 14:49:14 +010030import android.view.WindowInsetsController.Appearance;
Brett Chabot84151d92019-02-27 15:37:59 -080031
32import androidx.test.filters.SmallTest;
Jason Monkb5b092012017-01-05 11:35:34 -050033
34import com.android.internal.statusbar.StatusBarIcon;
Jorim Jaggi956ca412019-01-07 14:49:14 +010035import com.android.internal.view.AppearanceRegion;
Jason Monkb5b092012017-01-05 11:35:34 -050036import com.android.systemui.SysuiTestCase;
37import com.android.systemui.statusbar.CommandQueue.Callbacks;
38
39import org.junit.After;
40import org.junit.Before;
41import org.junit.Test;
42
Jason Monkfba8faf2017-05-23 10:42:59 -040043@SmallTest
Jason Monkb5b092012017-01-05 11:35:34 -050044public class CommandQueueTest extends SysuiTestCase {
45
46 private CommandQueue mCommandQueue;
47 private Callbacks mCallbacks;
Charles Chen54fce2c2019-03-13 18:17:29 +080048 private static final int SECONDARY_DISPLAY = 1;
Jason Monkb5b092012017-01-05 11:35:34 -050049
50 @Before
51 public void setup() {
Charles Chenf3d295c2018-11-30 18:15:21 +080052 mCommandQueue = new CommandQueue(mContext);
Jason Monkb5b092012017-01-05 11:35:34 -050053 mCallbacks = mock(Callbacks.class);
Jason Monkd7c98552018-12-04 11:14:50 -050054 mCommandQueue.addCallback(mCallbacks);
Charles Chenf3d295c2018-11-30 18:15:21 +080055 verify(mCallbacks).disable(anyInt(), eq(0), eq(0), eq(false));
Jason Monkb5b092012017-01-05 11:35:34 -050056 }
57
58 @After
59 public void tearDown() {
60 verifyNoMoreInteractions(mCallbacks);
61 }
62
63 @Test
64 public void testIcon() {
65 String slot = "testSlot";
66 StatusBarIcon icon = mock(StatusBarIcon.class);
67 mCommandQueue.setIcon(slot, icon);
68 waitForIdleSync();
69 verify(mCallbacks).setIcon(eq(slot), eq(icon));
70
71 mCommandQueue.removeIcon(slot);
72 waitForIdleSync();
73 verify(mCallbacks).removeIcon(eq(slot));
74 }
75
76 @Test
77 public void testDisable() {
78 int state1 = 14;
79 int state2 = 42;
Charles Chen24e7a9f2018-11-21 11:59:07 +080080 mCommandQueue.disable(DEFAULT_DISPLAY, state1, state2);
Jason Monkb5b092012017-01-05 11:35:34 -050081 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +080082 verify(mCallbacks).disable(eq(DEFAULT_DISPLAY), eq(state1), eq(state2), eq(true));
Jason Monkb5b092012017-01-05 11:35:34 -050083 }
84
85 @Test
Charles Chen54fce2c2019-03-13 18:17:29 +080086 public void testDisableForSecondaryDisplay() {
87 int state1 = 14;
88 int state2 = 42;
89 mCommandQueue.disable(SECONDARY_DISPLAY, state1, state2);
90 waitForIdleSync();
91 verify(mCallbacks).disable(eq(SECONDARY_DISPLAY), eq(state1), eq(state2), eq(true));
92 }
93
94 @Test
Jason Monkb5b092012017-01-05 11:35:34 -050095 public void testExpandNotifications() {
96 mCommandQueue.animateExpandNotificationsPanel();
97 waitForIdleSync();
98 verify(mCallbacks).animateExpandNotificationsPanel();
99 }
100
101 @Test
102 public void testCollapsePanels() {
103 mCommandQueue.animateCollapsePanels();
104 waitForIdleSync();
Jason Monk297c04e2018-08-23 17:16:59 -0400105 verify(mCallbacks).animateCollapsePanels(eq(0), eq(false));
Jason Monkb5b092012017-01-05 11:35:34 -0500106 }
107
108 @Test
109 public void testExpandSettings() {
110 String panel = "some_panel";
111 mCommandQueue.animateExpandSettingsPanel(panel);
112 waitForIdleSync();
113 verify(mCallbacks).animateExpandSettingsPanel(eq(panel));
114 }
115
116 @Test
Jorim Jaggi956ca412019-01-07 14:49:14 +0100117 public void testOnSystemBarAppearanceChanged() {
118 doTestOnSystemBarAppearanceChanged(DEFAULT_DISPLAY, 1,
119 new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
Jason Monkb5b092012017-01-05 11:35:34 -0500120 }
121
Charles Chen54fce2c2019-03-13 18:17:29 +0800122 @Test
Jorim Jaggi956ca412019-01-07 14:49:14 +0100123 public void testOnSystemBarAppearanceChangedForSecondaryDisplay() {
124 doTestOnSystemBarAppearanceChanged(SECONDARY_DISPLAY, 1,
125 new AppearanceRegion[]{new AppearanceRegion(2, new Rect())}, false);
126 }
127
128 private void doTestOnSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
129 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
130 mCommandQueue.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
131 navbarColorManagedByIme);
Charles Chen54fce2c2019-03-13 18:17:29 +0800132 waitForIdleSync();
Jorim Jaggi956ca412019-01-07 14:49:14 +0100133 verify(mCallbacks).onSystemBarAppearanceChanged(eq(displayId), eq(appearance),
134 eq(appearanceRegions), eq(navbarColorManagedByIme));
135 }
136
137 @Test
138 public void testShowTransient() {
Tiger Huang332793b2019-10-29 23:21:27 +0800139 int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
Jorim Jaggi956ca412019-01-07 14:49:14 +0100140 mCommandQueue.showTransient(DEFAULT_DISPLAY, types);
141 waitForIdleSync();
142 verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types));
143 }
144
145 @Test
146 public void testShowTransientForSecondaryDisplay() {
Tiger Huang332793b2019-10-29 23:21:27 +0800147 int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
Jorim Jaggi956ca412019-01-07 14:49:14 +0100148 mCommandQueue.showTransient(SECONDARY_DISPLAY, types);
149 waitForIdleSync();
150 verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types));
151 }
152
153 @Test
154 public void testAbortTransient() {
Tiger Huang332793b2019-10-29 23:21:27 +0800155 int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
Jorim Jaggi956ca412019-01-07 14:49:14 +0100156 mCommandQueue.abortTransient(DEFAULT_DISPLAY, types);
157 waitForIdleSync();
158 verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types));
159 }
160
161 @Test
162 public void testAbortTransientForSecondaryDisplay() {
Tiger Huang332793b2019-10-29 23:21:27 +0800163 int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
Jorim Jaggi956ca412019-01-07 14:49:14 +0100164 mCommandQueue.abortTransient(SECONDARY_DISPLAY, types);
165 waitForIdleSync();
166 verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types));
Charles Chen54fce2c2019-03-13 18:17:29 +0800167 }
168
Jason Monkb5b092012017-01-05 11:35:34 -0500169 @Test
Jason Monkb5b092012017-01-05 11:35:34 -0500170 public void testShowImeButton() {
Tarandeep Singh07b318b2019-07-17 11:12:04 -0700171 mCommandQueue.setImeWindowStatus(DEFAULT_DISPLAY, null, 1, 2, true, false);
Jason Monkb5b092012017-01-05 11:35:34 -0500172 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800173 verify(mCallbacks).setImeWindowStatus(
174 eq(DEFAULT_DISPLAY), eq(null), eq(1), eq(2), eq(true));
Jason Monkb5b092012017-01-05 11:35:34 -0500175 }
176
177 @Test
Charles Chen54fce2c2019-03-13 18:17:29 +0800178 public void testShowImeButtonForSecondaryDisplay() {
Tarandeep Singh07b318b2019-07-17 11:12:04 -0700179 mCommandQueue.setImeWindowStatus(SECONDARY_DISPLAY, null, 1, 2, true, false);
Charles Chen54fce2c2019-03-13 18:17:29 +0800180 waitForIdleSync();
181 verify(mCallbacks).setImeWindowStatus(
182 eq(SECONDARY_DISPLAY), eq(null), eq(1), eq(2), eq(true));
183 }
184
185 @Test
Jason Monkb5b092012017-01-05 11:35:34 -0500186 public void testShowRecentApps() {
Winson Chungdff7a732017-12-11 12:17:06 -0800187 mCommandQueue.showRecentApps(true);
Jason Monkb5b092012017-01-05 11:35:34 -0500188 waitForIdleSync();
Winson Chungdff7a732017-12-11 12:17:06 -0800189 verify(mCallbacks).showRecentApps(eq(true));
Jason Monkb5b092012017-01-05 11:35:34 -0500190 }
191
192 @Test
193 public void testHideRecentApps() {
194 mCommandQueue.hideRecentApps(true, false);
195 waitForIdleSync();
196 verify(mCallbacks).hideRecentApps(eq(true), eq(false));
197 }
198
199 @Test
200 public void testToggleRecentApps() {
201 mCommandQueue.toggleRecentApps();
202 waitForIdleSync();
203 verify(mCallbacks).toggleRecentApps();
204 }
205
206 @Test
207 public void testPreloadRecentApps() {
208 mCommandQueue.preloadRecentApps();
209 waitForIdleSync();
210 verify(mCallbacks).preloadRecentApps();
211 }
212
213 @Test
214 public void testCancelPreloadRecentApps() {
215 mCommandQueue.cancelPreloadRecentApps();
216 waitForIdleSync();
217 verify(mCallbacks).cancelPreloadRecentApps();
218 }
219
220 @Test
221 public void testDismissKeyboardShortcuts() {
222 mCommandQueue.dismissKeyboardShortcutsMenu();
223 waitForIdleSync();
224 verify(mCallbacks).dismissKeyboardShortcutsMenu();
225 }
226
227 @Test
228 public void testToggleKeyboardShortcuts() {
229 mCommandQueue.toggleKeyboardShortcutsMenu(1);
230 waitForIdleSync();
231 verify(mCallbacks).toggleKeyboardShortcutsMenu(eq(1));
232 }
233
234 @Test
235 public void testSetWindowState() {
Charles Chen24e7a9f2018-11-21 11:59:07 +0800236 mCommandQueue.setWindowState(DEFAULT_DISPLAY, 1, 2);
Jason Monkb5b092012017-01-05 11:35:34 -0500237 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800238 verify(mCallbacks).setWindowState(eq(DEFAULT_DISPLAY), eq(1), eq(2));
Jason Monkb5b092012017-01-05 11:35:34 -0500239 }
240
241 @Test
Charles Chen54fce2c2019-03-13 18:17:29 +0800242 public void testSetWindowStateForSecondaryDisplay() {
243 mCommandQueue.setWindowState(SECONDARY_DISPLAY, 1, 2);
244 waitForIdleSync();
245 verify(mCallbacks).setWindowState(eq(SECONDARY_DISPLAY), eq(1), eq(2));
246 }
247
248 @Test
Jason Monkb5b092012017-01-05 11:35:34 -0500249 public void testScreenPinRequest() {
250 mCommandQueue.showScreenPinningRequest(1);
251 waitForIdleSync();
252 verify(mCallbacks).showScreenPinningRequest(eq(1));
253 }
254
255 @Test
256 public void testAppTransitionPending() {
Charles Chen24e7a9f2018-11-21 11:59:07 +0800257 mCommandQueue.appTransitionPending(DEFAULT_DISPLAY);
Jason Monkb5b092012017-01-05 11:35:34 -0500258 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800259 verify(mCallbacks).appTransitionPending(eq(DEFAULT_DISPLAY), eq(false));
Jason Monkb5b092012017-01-05 11:35:34 -0500260 }
261
Charles Chen54fce2c2019-03-13 18:17:29 +0800262 @Test
263 public void testAppTransitionPendingForSecondaryDisplay() {
264 mCommandQueue.appTransitionPending(SECONDARY_DISPLAY);
265 waitForIdleSync();
266 verify(mCallbacks).appTransitionPending(eq(SECONDARY_DISPLAY), eq(false));
267 }
268
Jason Monkb5b092012017-01-05 11:35:34 -0500269 @Test
270 public void testAppTransitionCancelled() {
Charles Chen24e7a9f2018-11-21 11:59:07 +0800271 mCommandQueue.appTransitionCancelled(DEFAULT_DISPLAY);
Jason Monkb5b092012017-01-05 11:35:34 -0500272 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800273 verify(mCallbacks).appTransitionCancelled(eq(DEFAULT_DISPLAY));
Jason Monkb5b092012017-01-05 11:35:34 -0500274 }
275
Charles Chen54fce2c2019-03-13 18:17:29 +0800276 @Test
277 public void testAppTransitionCancelledForSecondaryDisplay() {
278 mCommandQueue.appTransitionCancelled(SECONDARY_DISPLAY);
279 waitForIdleSync();
280 verify(mCallbacks).appTransitionCancelled(eq(SECONDARY_DISPLAY));
281 }
282
Jason Monkb5b092012017-01-05 11:35:34 -0500283 @Test
284 public void testAppTransitionStarting() {
Charles Chen24e7a9f2018-11-21 11:59:07 +0800285 mCommandQueue.appTransitionStarting(DEFAULT_DISPLAY, 1, 2);
Jason Monkb5b092012017-01-05 11:35:34 -0500286 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800287 verify(mCallbacks).appTransitionStarting(
288 eq(DEFAULT_DISPLAY), eq(1L), eq(2L), eq(false));
Jason Monkb5b092012017-01-05 11:35:34 -0500289 }
290
Charles Chen54fce2c2019-03-13 18:17:29 +0800291 @Test
292 public void testAppTransitionStartingForSecondaryDisplay() {
293 mCommandQueue.appTransitionStarting(SECONDARY_DISPLAY, 1, 2);
294 waitForIdleSync();
295 verify(mCallbacks).appTransitionStarting(
296 eq(SECONDARY_DISPLAY), eq(1L), eq(2L), eq(false));
297 }
298
Jason Monkb5b092012017-01-05 11:35:34 -0500299 @Test
300 public void testAppTransitionFinished() {
Charles Chen24e7a9f2018-11-21 11:59:07 +0800301 mCommandQueue.appTransitionFinished(DEFAULT_DISPLAY);
Jason Monkb5b092012017-01-05 11:35:34 -0500302 waitForIdleSync();
Charles Chenf3d295c2018-11-30 18:15:21 +0800303 verify(mCallbacks).appTransitionFinished(eq(DEFAULT_DISPLAY));
Jason Monkb5b092012017-01-05 11:35:34 -0500304 }
305
306 @Test
Charles Chen54fce2c2019-03-13 18:17:29 +0800307 public void testAppTransitionFinishedForSecondaryDisplay() {
308 mCommandQueue.appTransitionFinished(SECONDARY_DISPLAY);
309 waitForIdleSync();
310 verify(mCallbacks).appTransitionFinished(eq(SECONDARY_DISPLAY));
311 }
312
313 @Test
Jason Monkb5b092012017-01-05 11:35:34 -0500314 public void testAssistDisclosure() {
315 mCommandQueue.showAssistDisclosure();
316 waitForIdleSync();
317 verify(mCallbacks).showAssistDisclosure();
318 }
319
320 @Test
321 public void testStartAssist() {
322 Bundle b = new Bundle();
323 mCommandQueue.startAssist(b);
324 waitForIdleSync();
325 verify(mCallbacks).startAssist(eq(b));
326 }
327
328 @Test
329 public void testCameraLaunchGesture() {
330 mCommandQueue.onCameraLaunchGestureDetected(1);
331 waitForIdleSync();
332 verify(mCallbacks).onCameraLaunchGestureDetected(eq(1));
333 }
334
335 @Test
Winson Chungac52f282017-03-30 14:44:52 -0700336 public void testShowPipMenu() {
337 mCommandQueue.showPictureInPictureMenu();
Jason Monkb5b092012017-01-05 11:35:34 -0500338 waitForIdleSync();
Winson Chungac52f282017-03-30 14:44:52 -0700339 verify(mCallbacks).showPictureInPictureMenu();
Jason Monkb5b092012017-01-05 11:35:34 -0500340 }
341
342 @Test
343 public void testAddQsTile() {
344 ComponentName c = new ComponentName("testpkg", "testcls");
345 mCommandQueue.addQsTile(c);
346 waitForIdleSync();
347 verify(mCallbacks).addQsTile(eq(c));
348 }
349
350 @Test
351 public void testRemoveQsTile() {
352 ComponentName c = new ComponentName("testpkg", "testcls");
353 mCommandQueue.remQsTile(c);
354 waitForIdleSync();
355 verify(mCallbacks).remQsTile(eq(c));
356 }
357
358 @Test
359 public void testClickQsTile() {
360 ComponentName c = new ComponentName("testpkg", "testcls");
361 mCommandQueue.clickQsTile(c);
362 waitForIdleSync();
363 verify(mCallbacks).clickTile(eq(c));
364 }
365
366 @Test
367 public void testToggleAppSplitScreen() {
368 mCommandQueue.toggleSplitScreen();
369 waitForIdleSync();
370 verify(mCallbacks).toggleSplitScreen();
371 }
372
373 @Test
Philip Quinnc3a503d2017-07-18 23:23:41 -0700374 public void testHandleSysKey() {
375 mCommandQueue.handleSystemKey(1);
Jason Monkb5b092012017-01-05 11:35:34 -0500376 waitForIdleSync();
Philip Quinnc3a503d2017-07-18 23:23:41 -0700377 verify(mCallbacks).handleSystemKey(eq(1));
Jason Monkb5b092012017-01-05 11:35:34 -0500378 }
Charles Chen54fce2c2019-03-13 18:17:29 +0800379
380 @Test
381 public void testOnDisplayReady() {
382 mCommandQueue.onDisplayReady(DEFAULT_DISPLAY);
383 waitForIdleSync();
384 verify(mCallbacks).onDisplayReady(eq(DEFAULT_DISPLAY));
385 }
386
387 @Test
388 public void testOnDisplayReadyForSecondaryDisplay() {
389 mCommandQueue.onDisplayReady(SECONDARY_DISPLAY);
390 waitForIdleSync();
391 verify(mCallbacks).onDisplayReady(eq(SECONDARY_DISPLAY));
392 }
393
394 @Test
395 public void testOnDisplayRemoved() {
396 mCommandQueue.onDisplayRemoved(SECONDARY_DISPLAY);
397 waitForIdleSync();
398 verify(mCallbacks).onDisplayRemoved(eq(SECONDARY_DISPLAY));
399 }
Winson Chung67e49362019-05-17 16:40:38 -0700400
401 @Test
402 public void testOnRecentsAnimationStateChanged() {
403 mCommandQueue.onRecentsAnimationStateChanged(true);
404 waitForIdleSync();
405 verify(mCallbacks).onRecentsAnimationStateChanged(eq(true));
406 }
Kevin Chync53d9812019-07-30 18:10:30 -0700407
408 @Test
Kevin Chyn86f1b8e2019-09-24 19:00:49 -0700409 public void testShowAuthenticationDialog() {
Kevin Chync53d9812019-07-30 18:10:30 -0700410 Bundle bundle = new Bundle();
Kevin Chyn050315f2019-08-08 14:22:54 -0700411 String packageName = "test";
Kevin Chyn86f1b8e2019-09-24 19:00:49 -0700412 mCommandQueue.showAuthenticationDialog(bundle, null /* receiver */, 1, true, 3,
413 packageName);
Kevin Chync53d9812019-07-30 18:10:30 -0700414 waitForIdleSync();
Kevin Chyn86f1b8e2019-09-24 19:00:49 -0700415 verify(mCallbacks).showAuthenticationDialog(eq(bundle), eq(null), eq(1), eq(true), eq(3),
Kevin Chyn050315f2019-08-08 14:22:54 -0700416 eq(packageName));
Kevin Chync53d9812019-07-30 18:10:30 -0700417 }
418
419 @Test
420 public void testOnBiometricAuthenticated() {
Ilya Matyukhin0f9da352019-10-03 14:10:01 -0700421 mCommandQueue.onBiometricAuthenticated();
Kevin Chync53d9812019-07-30 18:10:30 -0700422 waitForIdleSync();
Ilya Matyukhin0f9da352019-10-03 14:10:01 -0700423 verify(mCallbacks).onBiometricAuthenticated();
Kevin Chync53d9812019-07-30 18:10:30 -0700424 }
425
426 @Test
427 public void testOnBiometricHelp() {
428 String helpMessage = "test_help_message";
429 mCommandQueue.onBiometricHelp(helpMessage);
430 waitForIdleSync();
431 verify(mCallbacks).onBiometricHelp(eq(helpMessage));
432 }
433
434 @Test
435 public void testOnBiometricError() {
Ilya Matyukhin0f9da352019-10-03 14:10:01 -0700436 final int modality = 1;
437 final int error = 2;
438 final int vendorCode = 3;
439 mCommandQueue.onBiometricError(modality, error, vendorCode);
Kevin Chync53d9812019-07-30 18:10:30 -0700440 waitForIdleSync();
Ilya Matyukhin0f9da352019-10-03 14:10:01 -0700441 verify(mCallbacks).onBiometricError(eq(modality), eq(error), eq(vendorCode));
Kevin Chync53d9812019-07-30 18:10:30 -0700442 }
443
444 @Test
Kevin Chyn86f1b8e2019-09-24 19:00:49 -0700445 public void testHideAuthenticationDialog() {
446 mCommandQueue.hideAuthenticationDialog();
Kevin Chync53d9812019-07-30 18:10:30 -0700447 waitForIdleSync();
Kevin Chyn86f1b8e2019-09-24 19:00:49 -0700448 verify(mCallbacks).hideAuthenticationDialog();
Kevin Chync53d9812019-07-30 18:10:30 -0700449 }
Jason Monkb5b092012017-01-05 11:35:34 -0500450}