18c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn/* 28c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Copyright (C) 2013 The Android Open Source Project 38c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 48c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 58c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * you may not use this file except in compliance with the License. 68c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * You may obtain a copy of the License at 78c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 88c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 98c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 108c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Unless required by applicable law or agreed to in writing, software 118c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 128c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * See the License for the specific language governing permissions and 148c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * limitations under the License. 158c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 168c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 178c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornpackage android.support.v4.media; 188c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 198c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornimport android.os.SystemClock; 208c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornimport android.view.KeyEvent; 218c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 228c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn/** 23e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Implemented by the playback side of the media system, to respond to 24e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * requests to perform actions and to retrieve its current state. These 25e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * requests may either come from key events dispatched directly to your UI, or 268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * events sent over a media button event receiver that this class keeps active 278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * while your window is in focus. 288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornpublic abstract class TransportPerformer { 30e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 31e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to start playback on the media, resuming from whatever current state 32e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * (position etc) it is in. 33e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onStart(); 358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 36e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 37e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to pause playback of the media, staying at the current playback position 38e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * and other state so a later call to {@link #onStart()} will resume at the same place. 39e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract void onPause(); 418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 42e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 43e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to completely stop playback of the media, clearing whatever state the 44e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * player thinks is appropriate. 45e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 46e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn public abstract void onStop(); 47e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn 48e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 49e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to return the duration of the current media, in milliseconds. 50e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 5154fe42a994b1aa1608d23a57a2f55228712e98e7Dianne Hackborn public abstract long onGetDuration(); 528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 53e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 54e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to return the current playback position, in milliseconds. 55e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 5654fe42a994b1aa1608d23a57a2f55228712e98e7Dianne Hackborn public abstract long onGetCurrentPosition(); 578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 58e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 59e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to move the current playback position. 60e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * @param pos New position to move to, in milliseconds. 61e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 6254fe42a994b1aa1608d23a57a2f55228712e98e7Dianne Hackborn public abstract void onSeekTo(long pos); 638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 64e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 65e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to find out whether the player is currently playing its media. 66e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public abstract boolean onIsPlaying(); 688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 69e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn /** 70e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Request to find out how much of the media has been buffered on the local device. 71e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * @return Return a percentage (0-100) indicating how much of the total data 72e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * has been buffered. The default implementation returns 100, meaning the content 73e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * is always on the local device. 74e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn */ 758c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public int onGetBufferPercentage() { 768c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return 100; 778c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 788c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 798c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 808c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Retrieves the flags for the media transport control buttons that this transport supports. 818c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Result is a combination of the following flags: 828c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS}, 838c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_REWIND}, 848c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 858c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 868c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, 878c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}, 888c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD}, 898c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_NEXT} 908c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * 918c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <p>The default implementation returns: 928c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY}, 938c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE}, 948c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and 958c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#FLAG_KEY_MEDIA_STOP}</p> 968c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 978c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public int onGetTransportControlFlags() { 988c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return TransportMediator.FLAG_KEY_MEDIA_PLAY 998c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE 1008c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_PAUSE 1018c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn | TransportMediator.FLAG_KEY_MEDIA_STOP; 1028c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1038c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1048c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 1058c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Report that a media button has been pressed. This is like 1068c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)} but 1078c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * will only deliver media keys. The default implementation handles these keys: 1088c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <ul> 1098c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PLAY: call {@link #onStart}</li> 1108c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PAUSE: call {@link #onPause}</li> 1118c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_STOP: call {@link #onStop}</li> 1128c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * <li>KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause} 1138c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}</li> 1148c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * </ul> 1158c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param keyCode The code of the media key. 1168c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param event The full key event. 1178c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @return Indicate whether the key has been consumed. The default 1188c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * implementation always returns true. This only matters for keys 1198c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being dispatched here from 1208c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 1218c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * TransportController.dispatchKeyEvent}, and determines whether the key 1228c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * continues on to its default key handling (which for media keys means 1238c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being delivered to the current media remote control, which should 1248c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * be us). 1258c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 1268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public boolean onMediaButtonDown(int keyCode, KeyEvent event) { 1278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn switch (keyCode) { 1288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case TransportMediator.KEYCODE_MEDIA_PLAY: 1298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStart(); 1308c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1318c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case TransportMediator.KEYCODE_MEDIA_PAUSE: 1328c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onPause(); 1338c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_MEDIA_STOP: 1358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStop(); 1368c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1378c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 1388c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case KeyEvent.KEYCODE_HEADSETHOOK: 1398c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn if (onIsPlaying()) { 1408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onPause(); 1418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } else { 1428c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onStart(); 1438c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1448c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1458c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1468c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1478c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1488c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 149e3f8e5a462e23399945e8042ddb8025ec8fa33acDianne Hackborn * Report that a media button has been released. This is like 1508c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link KeyEvent.Callback#onKeyUp(int, android.view.KeyEvent)} but 1518c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * will only deliver media keys. The default implementation does nothing. 1528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param keyCode The code of the media key. 1538c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param event The full key event. 1548c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @return Indicate whether the key has been consumed. The default 1558c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * implementation always returns true. This only matters for keys 1568c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being dispatched here from 1578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent) 1588c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * TransportController.dispatchKeyEvent}, and determines whether the key 1598c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * continues on to its default key handling (which for media keys means 1608c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * being delivered to the current media remote control, which should 1618c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * be us). 1628c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 1638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public boolean onMediaButtonUp(int keyCode, KeyEvent event) { 1648c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn return true; 1658c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1668c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // Copy constants from framework since we can't link to them. 1688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN = 1; 1698c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN_TRANSIENT = 2; 1708c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3; 1718c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN; 1728c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT; 1738c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = 1748c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 1758c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn 1768c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn /** 1778c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Report that audio focus has changed on the app. This only happens if 1788c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * you have indicated you have started playing with 1798c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link TransportMediator#startPlaying TransportController.startPlaying}, 1808c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * which takes audio focus for you. 1818c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * @param focusChange The type of focus change, as per 1828c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int) 1838c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * OnAudioFocusChangeListener.onAudioFocusChange}. The default implementation will 1848c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP} 1858c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}. 1868c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */ 1878c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn public void onAudioFocusChange(int focusChange) { 1888c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn int keyCode = 0; 1898c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn switch (focusChange) { 1908c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn case AUDIOFOCUS_LOSS: 1918c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // This will cause us to stop playback, which means we drop audio focus 1928c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn // so we will not get any further audio focus gain. 1938c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE; 1948c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn break; 1958c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 1968c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn if (keyCode != 0) { 1978c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn final long now = SystemClock.uptimeMillis(); 1988c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0)); 1998c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0)); 2008c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 2018c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn } 2028c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn} 203