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