TransportPerformer.java revision 8c7c4c0409bd93f66fe39c5a5298a94f832be31e
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/**
238c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * Class through which you receive information about media transport actions.
248c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * These may either come from key events dispatched directly to your UI, or
258c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * events sent over a media button event receiver that this class keeps active
268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn * while your window is in focus.
278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn */
288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackbornpublic abstract class TransportPerformer {
298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract void onStart();
308c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
318c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract void onStop();
328c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
338c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract void onPause();
348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract int onGetDuration();
368c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
378c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract int onGetCurrentPosition();
388c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
398c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract void onSeekTo(int pos);
408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public abstract boolean onIsPlaying();
428c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
438c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public int onGetBufferPercentage() {
448c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        return 100;
458c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    }
468c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
478c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    /**
488c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * Retrieves the flags for the media transport control buttons that this transport supports.
498c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * Result is a combination of the following flags:
508c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PREVIOUS},
518c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_REWIND},
528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PLAY},
538c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE},
548c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE},
558c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_STOP},
568c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_FAST_FORWARD},
578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_NEXT}
588c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *
598c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * <p>The default implementation returns:
608c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PLAY},
618c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PLAY_PAUSE},
628c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_PAUSE}, and
638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *      {@link TransportMediator#FLAG_KEY_MEDIA_STOP}</p>
648c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     */
658c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public int onGetTransportControlFlags() {
668c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        return TransportMediator.FLAG_KEY_MEDIA_PLAY
678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE
688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                | TransportMediator.FLAG_KEY_MEDIA_PAUSE
698c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                | TransportMediator.FLAG_KEY_MEDIA_STOP;
708c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    }
718c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
728c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    /**
738c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * Report that a media button has been pressed.  This is like
748c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link android.view.KeyEvent.Callback#onKeyDown(int, android.view.KeyEvent)} but
758c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * will only deliver media keys.  The default implementation handles these keys:
768c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * <ul>
778c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *     <li>KEYCODE_MEDIA_PLAY: call {@link #onStart}</li>
788c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *     <li>KEYCODE_MEDIA_PAUSE: call {@link #onPause}</li>
798c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *     <li>KEYCODE_MEDIA_STOP: call {@link #onStop}</li>
808c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *     <li>KEYCODE_MEDIA_PLAY_PAUSE and KEYCODE_HEADSETHOOK: call {@link #onPause}
818c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     *          if {@link #onIsPlaying()} returns true, otherwise call {@link #onStart}</li>
828c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * </ul>
838c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @param keyCode The code of the media key.
848c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @param event The full key event.
858c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @return Indicate whether the key has been consumed.  The default
868c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * implementation always returns true.  This only matters for keys
878c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * being dispatched here from
888c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent)
898c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * TransportController.dispatchKeyEvent}, and determines whether the key
908c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * continues on to its default key handling (which for media keys means
918c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * being delivered to the current media remote control, which should
928c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * be us).
938c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     */
948c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public boolean onMediaButtonDown(int keyCode, KeyEvent event) {
958c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        switch (keyCode) {
968c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case TransportMediator.KEYCODE_MEDIA_PLAY:
978c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                onStart();
988c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                return true;
998c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case TransportMediator.KEYCODE_MEDIA_PAUSE:
1008c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                onPause();
1018c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                return true;
1028c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case KeyEvent.KEYCODE_MEDIA_STOP:
1038c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                onStop();
1048c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                return true;
1058c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
1068c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case KeyEvent.KEYCODE_HEADSETHOOK:
1078c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                if (onIsPlaying()) {
1088c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                    onPause();
1098c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                } else {
1108c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                    onStart();
1118c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                }
1128c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        }
1138c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        return true;
1148c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    }
1158c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
1168c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    /**
1178c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * Report that a media button has been pressed.  This is like
1188c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link KeyEvent.Callback#onKeyUp(int, android.view.KeyEvent)} but
1198c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * will only deliver media keys.  The default implementation does nothing.
1208c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @param keyCode The code of the media key.
1218c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @param event The full key event.
1228c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @return Indicate whether the key has been consumed.  The default
1238c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * implementation always returns true.  This only matters for keys
1248c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * being dispatched here from
1258c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link TransportMediator#dispatchKeyEvent(android.view.KeyEvent)
1268c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * TransportController.dispatchKeyEvent}, and determines whether the key
1278c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * continues on to its default key handling (which for media keys means
1288c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * being delivered to the current media remote control, which should
1298c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * be us).
1308c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     */
1318c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public boolean onMediaButtonUp(int keyCode, KeyEvent event) {
1328c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        return true;
1338c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    }
1348c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
1358c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    // Copy constants from framework since we can't link to them.
1368c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_GAIN = 1;
1378c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
1388c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
1398c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
1408c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
1418c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
1428c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
1438c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn
1448c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    /**
1458c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * Report that audio focus has changed on the app.  This only happens if
1468c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * you have indicated you have started playing with
1478c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link TransportMediator#startPlaying TransportController.startPlaying},
1488c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * which takes audio focus for you.
1498c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * @param focusChange The type of focus change, as per
1508c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int)
1518c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * OnAudioFocusChangeListener.onAudioFocusChange}.  The default implementation will
1528c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * deliver a {@link KeyEvent#KEYCODE_MEDIA_STOP}
1538c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     * when receiving {@link android.media.AudioManager#AUDIOFOCUS_LOSS}.
1548c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn     */
1558c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    public void onAudioFocusChange(int focusChange) {
1568c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        int keyCode = 0;
1578c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        switch (focusChange) {
1588c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            case AUDIOFOCUS_LOSS:
1598c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                // This will cause us to stop playback, which means we drop audio focus
1608c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                // so we will not get any further audio focus gain.
1618c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                keyCode = TransportMediator.KEYCODE_MEDIA_PAUSE;
1628c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn                break;
1638c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        }
1648c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        if (keyCode != 0) {
1658c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            final long now = SystemClock.uptimeMillis();
1668c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            onMediaButtonDown(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0));
1678c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn            onMediaButtonUp(keyCode, new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0));
1688c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn        }
1698c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn    }
1708c7c4c0409bd93f66fe39c5a5298a94f832be31eDianne Hackborn}
171