TvStatusBar.java revision 67ed54a724df258738062e60d7f702f396502b49
1acad183238ad13774dba38c403ed553c2427027eChristopher Tate/* 2acad183238ad13774dba38c403ed553c2427027eChristopher Tate * Copyright (C) 2012 The Android Open Source Project 3acad183238ad13774dba38c403ed553c2427027eChristopher Tate * 4acad183238ad13774dba38c403ed553c2427027eChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 5acad183238ad13774dba38c403ed553c2427027eChristopher Tate * you may not use this file except in compliance with the License. 6acad183238ad13774dba38c403ed553c2427027eChristopher Tate * You may obtain a copy of the License at 7acad183238ad13774dba38c403ed553c2427027eChristopher Tate * 8acad183238ad13774dba38c403ed553c2427027eChristopher Tate * http://www.apache.org/licenses/LICENSE-2.0 9acad183238ad13774dba38c403ed553c2427027eChristopher Tate * 10acad183238ad13774dba38c403ed553c2427027eChristopher Tate * Unless required by applicable law or agreed to in writing, software 11acad183238ad13774dba38c403ed553c2427027eChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 12acad183238ad13774dba38c403ed553c2427027eChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13acad183238ad13774dba38c403ed553c2427027eChristopher Tate * See the License for the specific language governing permissions and 14acad183238ad13774dba38c403ed553c2427027eChristopher Tate * limitations under the License. 15acad183238ad13774dba38c403ed553c2427027eChristopher Tate */ 16acad183238ad13774dba38c403ed553c2427027eChristopher Tate 17acad183238ad13774dba38c403ed553c2427027eChristopher Tatepackage com.android.systemui.statusbar.tv; 18acad183238ad13774dba38c403ed553c2427027eChristopher Tate 197e53f20c835ae2614c92717a6fc222b345c75036Jason Monkimport android.content.ComponentName; 2086905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggiimport android.graphics.Rect; 21acad183238ad13774dba38c403ed553c2427027eChristopher Tateimport android.os.IBinder; 2267ed54a724df258738062e60d7f702f396502b49Sid Soundararajanimport android.os.RemoteException; 23d0694b6735a9d91794e6096961231e07364ba3faChristoph Studerimport android.service.notification.NotificationListenerService.RankingMap; 24de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport android.service.notification.StatusBarNotification; 25acad183238ad13774dba38c403ed553c2427027eChristopher Tateimport android.view.View; 26acad183238ad13774dba38c403ed553c2427027eChristopher Tate 27de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport com.android.internal.statusbar.StatusBarIcon; 28a32ab60bb020df1d89fadfa14eb8600242786bf2Selim Cinekimport com.android.systemui.statusbar.ActivatableNotificationView; 29de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport com.android.systemui.statusbar.BaseStatusBar; 30379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinekimport com.android.systemui.statusbar.NotificationData; 31c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kimimport com.android.systemui.tv.pip.PipManager; 32de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlock 3367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan/** 34acad183238ad13774dba38c403ed553c2427027eChristopher Tate * Status bar implementation for "large screen" products that mostly present no on-screen nav 35acad183238ad13774dba38c403ed553c2427027eChristopher Tate */ 36acad183238ad13774dba38c403ed553c2427027eChristopher Tate 37acad183238ad13774dba38c403ed553c2427027eChristopher Tatepublic class TvStatusBar extends BaseStatusBar { 38acad183238ad13774dba38c403ed553c2427027eChristopher Tate 3967ed54a724df258738062e60d7f702f396502b49Sid Soundararajan /** 4067ed54a724df258738062e60d7f702f396502b49Sid Soundararajan * Tracking calls to View.setSystemUiVisibility(). 4167ed54a724df258738062e60d7f702f396502b49Sid Soundararajan */ 4267ed54a724df258738062e60d7f702f396502b49Sid Soundararajan int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 4367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan 4467ed54a724df258738062e60d7f702f396502b49Sid Soundararajan /** 4567ed54a724df258738062e60d7f702f396502b49Sid Soundararajan * Last value sent to window manager. 4667ed54a724df258738062e60d7f702f396502b49Sid Soundararajan */ 4767ed54a724df258738062e60d7f702f396502b49Sid Soundararajan private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE; 4867ed54a724df258738062e60d7f702f396502b49Sid Soundararajan 49acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 5007473cea3a6007d5e72b25d3445437a175735fa9Jason Monk public void setIcon(String slot, StatusBarIcon icon) { 51acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 52acad183238ad13774dba38c403ed553c2427027eChristopher Tate 53acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 5407473cea3a6007d5e72b25d3445437a175735fa9Jason Monk public void removeIcon(String slot) { 55acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 56acad183238ad13774dba38c403ed553c2427027eChristopher Tate 57acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 58379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinek public void addNotification(StatusBarNotification notification, RankingMap ranking, 59379ff8f6b18b236b679a59a2dc14c0baeede3baeSelim Cinek NotificationData.Entry entry) { 60acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 61acad183238ad13774dba38c403ed553c2427027eChristopher Tate 62acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 63e71fefcc8b382947f6f6a8bf816b3889fb368fedChristoph Studer protected void updateNotificationRanking(RankingMap ranking) { 6460748e7122c6cfbcebcf4a283d1a78ca796d07a7Christoph Studer } 6560748e7122c6cfbcebcf4a283d1a78ca796d07a7Christoph Studer 6660748e7122c6cfbcebcf4a283d1a78ca796d07a7Christoph Studer @Override 67e71fefcc8b382947f6f6a8bf816b3889fb368fedChristoph Studer public void removeNotification(String key, RankingMap ranking) { 68acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 69acad183238ad13774dba38c403ed553c2427027eChristopher Tate 70acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 71cde0a2a9ea00d6e4acfe6ce7a7c9061343df7fa3Benjamin Franz public void disable(int state1, int state2, boolean animate) { 72acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 73acad183238ad13774dba38c403ed553c2427027eChristopher Tate 74acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 7511cf178100e71d3f9f34ab5865e03a277c5eadaaDaniel Sandler public void animateExpandNotificationsPanel() { 76acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 77acad183238ad13774dba38c403ed553c2427027eChristopher Tate 78acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 7911cf178100e71d3f9f34ab5865e03a277c5eadaaDaniel Sandler public void animateCollapsePanels(int flags) { 80acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 81acad183238ad13774dba38c403ed553c2427027eChristopher Tate 82acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 8386905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, 8486905582411c5c77a3e7641589cf206c6e5770f5Jorim Jaggi int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { 85acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 86acad183238ad13774dba38c403ed553c2427027eChristopher Tate 87acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 88acad183238ad13774dba38c403ed553c2427027eChristopher Tate public void topAppWindowChanged(boolean visible) { 89acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 90acad183238ad13774dba38c403ed553c2427027eChristopher Tate 91acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 92b605fecd9e4282823af754b3968b21205d64554aJason Monk public void setImeWindowStatus(IBinder token, int vis, int backDisposition, 93b605fecd9e4282823af754b3968b21205d64554aJason Monk boolean showImeSwitcher) { 94acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 95acad183238ad13774dba38c403ed553c2427027eChristopher Tate 96acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override // CommandQueue 979764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock public void setWindowState(int window, int state) { 989764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock } 999764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock 100cad5768e22e5132efb2e5179f4988a763c7a8d9eJohn Spurlock @Override // CommandQueue 101cad5768e22e5132efb2e5179f4988a763c7a8d9eJohn Spurlock public void buzzBeepBlinked() { 102cad5768e22e5132efb2e5179f4988a763c7a8d9eJohn Spurlock } 103cad5768e22e5132efb2e5179f4988a763c7a8d9eJohn Spurlock 104cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock @Override // CommandQueue 105cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock public void notificationLightOff() { 106cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock } 107cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock 108cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock @Override // CommandQueue 109cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock public void notificationLightPulse(int argb, int onMillis, int offMillis) { 110cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock } 111cb566aab57cafb69c628809fc0a0ffa2151c7d6eJohn Spurlock 112acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 113acad183238ad13774dba38c403ed553c2427027eChristopher Tate protected void setAreThereNotifications() { 114acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 115acad183238ad13774dba38c403ed553c2427027eChristopher Tate 116acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 11737fe69322517809d38c1934239a6e117c39d40e7Christoph Studer protected void updateNotifications() { 118acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 119acad183238ad13774dba38c403ed553c2427027eChristopher Tate 120acad183238ad13774dba38c403ed553c2427027eChristopher Tate @Override 1212fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public boolean shouldDisableNavbarGestures() { 122acad183238ad13774dba38c403ed553c2427027eChristopher Tate return true; 123acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 124acad183238ad13774dba38c403ed553c2427027eChristopher Tate 125cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka public View getStatusBarView() { 126cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka return null; 127cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka } 128cb2522c86d75fff277dc38ec7e444a5b5f5130eaMichael Jurka 129e20a177d3f147f3011647c3bdab401f90b2c5d1dSvetoslav Ganov @Override 130315c34e7d62ce4b609f2d08b18a11a2d44e93abaPhil Weaver protected boolean toggleSplitScreenMode() { 131315c34e7d62ce4b609f2d08b18a11a2d44e93abaPhil Weaver return false; 132315c34e7d62ce4b609f2d08b18a11a2d44e93abaPhil Weaver } 133315c34e7d62ce4b609f2d08b18a11a2d44e93abaPhil Weaver 134315c34e7d62ce4b609f2d08b18a11a2d44e93abaPhil Weaver @Override 135684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek public void maybeEscalateHeadsUp() { 136a4ef6203262d45d4ffae7860ef40bd931ab27e07Chris Wren } 137a4ef6203262d45d4ffae7860ef40bd931ab27e07Chris Wren 138a4ef6203262d45d4ffae7860ef40bd931ab27e07Chris Wren @Override 139e4ea6ab1e71b129f08aff118b9dbaab7c559841dYorke Lee public boolean isPanelFullyCollapsed() { 1401689594851a6dd985cff69913e7f4bc548062808Chris Wren return false; 1411689594851a6dd985cff69913e7f4bc548062808Chris Wren } 1421689594851a6dd985cff69913e7f4bc548062808Chris Wren 1431689594851a6dd985cff69913e7f4bc548062808Chris Wren @Override 1445f71bee3a83fa9465f03dcd1108c038f0339e3c5Selim Cinek protected int getMaxKeyguardNotifications(boolean recompute) { 145d4a57440ca5fc8461959176475b0fcd8a6e05871Jorim Jaggi return 0; 146d4a57440ca5fc8461959176475b0fcd8a6e05871Jorim Jaggi } 147d4a57440ca5fc8461959176475b0fcd8a6e05871Jorim Jaggi 148d4a57440ca5fc8461959176475b0fcd8a6e05871Jorim Jaggi @Override 149a9927325eda025504d59bb6594fee8e240d95b01Jason Monk public void animateExpandSettingsPanel(String subPanel) { 150acad183238ad13774dba38c403ed553c2427027eChristopher Tate } 1518afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio 1528afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio @Override 1535cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi protected void createAndAddWindows() { 1545cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi } 1555cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi 1565cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi @Override 1578afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio protected void refreshLayout(int layoutDirection) { 1588afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio } 1598afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio 160d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi @Override 161a32ab60bb020df1d89fadfa14eb8600242786bf2Selim Cinek public void onActivated(ActivatableNotificationView view) { 162d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 163d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi 164d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi @Override 165a32ab60bb020df1d89fadfa14eb8600242786bf2Selim Cinek public void onActivationReset(ActivatableNotificationView view) { 166d552d9d8e964c102e6832610be46cf2c041e8829Jorim Jaggi } 1675565cb42f2ac07fcdbe3aab2503de07fbeb39504Jason Monk 1685565cb42f2ac07fcdbe3aab2503de07fbeb39504Jason Monk @Override 1695565cb42f2ac07fcdbe3aab2503de07fbeb39504Jason Monk public void showScreenPinningRequest() { 1705565cb42f2ac07fcdbe3aab2503de07fbeb39504Jason Monk } 17124bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi 17224bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi @Override 17324bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi public void appTransitionPending() { 17424bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi } 17524bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi 17624bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi @Override 17724bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi public void appTransitionCancelled() { 17824bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi } 17924bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi 18024bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi @Override 18124bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi public void appTransitionStarting(long startTime, long duration) { 18224bec7ce7adc3c0d693cfadcb4b28f5fc41555aeJorim Jaggi } 18329fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek 18429fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek @Override 1852adba07d75419462873dfeef40d4c983d832ed99Jorim Jaggi public void appTransitionFinished() { 1862adba07d75419462873dfeef40d4c983d832ed99Jorim Jaggi } 1872adba07d75419462873dfeef40d4c983d832ed99Jorim Jaggi 1882adba07d75419462873dfeef40d4c983d832ed99Jorim Jaggi @Override 18940aa8811bc817293d7400c14fa60350d2350d29fJorim Jaggi public void onCameraLaunchGestureDetected(int source) { 190372d1bdd54fe977c71bdaae895687c76ac35202aSelim Cinek } 191372d1bdd54fe977c71bdaae895687c76ac35202aSelim Cinek 192372d1bdd54fe977c71bdaae895687c76ac35202aSelim Cinek @Override 193c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kim public void requestTvPictureInPicture() { 194c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kim PipManager.getInstance().requestTvPictureInPicture(); 195c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kim } 196c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kim 197c552b04cb4aac9d31dbaf9744f32ddc14886e222Jaewan Kim @Override 198bdf3376616c276ed18a51185351b44fd16eeae29Chris Wren protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldPeek, 19929fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek boolean alertAgain) { 20029fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek } 20129fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek 20229fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek @Override 20329fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek protected void setHeadsUpUser(int newUserId) { 20429fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek } 20529fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek 20629fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek protected boolean isSnoozedPackage(StatusBarNotification sbn) { 20729fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek return false; 20829fa89b41e15ee61a1ec13307596fe5f5f4c376cSelim Cinek } 2097e53f20c835ae2614c92717a6fc222b345c75036Jason Monk 2107e53f20c835ae2614c92717a6fc222b345c75036Jason Monk @Override 2117e53f20c835ae2614c92717a6fc222b345c75036Jason Monk public void addQsTile(ComponentName tile) { 2127e53f20c835ae2614c92717a6fc222b345c75036Jason Monk } 2137e53f20c835ae2614c92717a6fc222b345c75036Jason Monk 2147e53f20c835ae2614c92717a6fc222b345c75036Jason Monk @Override 2157e53f20c835ae2614c92717a6fc222b345c75036Jason Monk public void remQsTile(ComponentName tile) { 2167e53f20c835ae2614c92717a6fc222b345c75036Jason Monk } 2177e53f20c835ae2614c92717a6fc222b345c75036Jason Monk 2187e53f20c835ae2614c92717a6fc222b345c75036Jason Monk @Override 2197e53f20c835ae2614c92717a6fc222b345c75036Jason Monk public void clickTile(ComponentName tile) { 2207e53f20c835ae2614c92717a6fc222b345c75036Jason Monk } 22167ed54a724df258738062e60d7f702f396502b49Sid Soundararajan 22267ed54a724df258738062e60d7f702f396502b49Sid Soundararajan @Override 22367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan public void start() { 22467ed54a724df258738062e60d7f702f396502b49Sid Soundararajan super.start(); 22567ed54a724df258738062e60d7f702f396502b49Sid Soundararajan putComponent(TvStatusBar.class, this); 22667ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 22767ed54a724df258738062e60d7f702f396502b49Sid Soundararajan 22867ed54a724df258738062e60d7f702f396502b49Sid Soundararajan public void updateRecentsVisibility(boolean visible) { 22967ed54a724df258738062e60d7f702f396502b49Sid Soundararajan // Update the recents visibility flag 23067ed54a724df258738062e60d7f702f396502b49Sid Soundararajan if (visible) { 23167ed54a724df258738062e60d7f702f396502b49Sid Soundararajan mSystemUiVisibility |= View.RECENT_APPS_VISIBLE; 23267ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } else { 23367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE; 23467ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 23567ed54a724df258738062e60d7f702f396502b49Sid Soundararajan notifyUiVisibilityChanged(mSystemUiVisibility); 23667ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 23767ed54a724df258738062e60d7f702f396502b49Sid Soundararajan 23867ed54a724df258738062e60d7f702f396502b49Sid Soundararajan private void notifyUiVisibilityChanged(int vis) { 23967ed54a724df258738062e60d7f702f396502b49Sid Soundararajan try { 24067ed54a724df258738062e60d7f702f396502b49Sid Soundararajan if (mLastDispatchedSystemUiVisibility != vis) { 24167ed54a724df258738062e60d7f702f396502b49Sid Soundararajan mWindowManagerService.statusBarVisibilityChanged(vis); 24267ed54a724df258738062e60d7f702f396502b49Sid Soundararajan mLastDispatchedSystemUiVisibility = vis; 24367ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 24467ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } catch (RemoteException ex) { 24567ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 24667ed54a724df258738062e60d7f702f396502b49Sid Soundararajan } 247acad183238ad13774dba38c403ed553c2427027eChristopher Tate} 248