RemoteControlClient.java revision 4426e42ac6107bf6b09f7c4cdad39eb161d8b9ca
1178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi/*
2178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Copyright (C) 2011 The Android Open Source Project
3178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi *
4178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * you may not use this file except in compliance with the License.
6178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * You may obtain a copy of the License at
7178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi *
8178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi *
10178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * See the License for the specific language governing permissions and
14178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * limitations under the License.
15178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */
16178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
17178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivipackage android.media;
18178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
19178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Triviimport android.content.ComponentName;
204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.content.SharedPreferences.Editor;
21178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Triviimport android.graphics.Bitmap;
224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.Canvas;
234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.Paint;
244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.RectF;
254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Bundle;
264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Handler;
274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Looper;
284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Message;
294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.RemoteException;
304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.util.Log;
314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport java.util.HashMap;
33178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
34178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi/**
35178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @hide
364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * CANDIDATE FOR SDK
374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * RemoteControlClient enables exposing information meant to be consumed by remote controls
38178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * capable of displaying metadata, album art and media transport control buttons.
394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * A remote control client object is associated with a media button event receiver
40178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * when registered through
414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}.
42178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */
434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivipublic class RemoteControlClient
44178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi{
454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static String TAG = "RemoteControlClient";
464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
47178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
48178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is stopped.
49178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
51178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
52178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_STOPPED            = 1;
53178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
54178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is paused.
55178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
57178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
58178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_PAUSED             = 2;
59178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
60178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is playing media.
61178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
63178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
64178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_PLAYING            = 3;
65178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
66178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is fast forwarding in the media
67178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    it is currently playing.
68178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
70178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
71178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_FAST_FORWARDING    = 4;
72178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
73178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is fast rewinding in the media
74178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    it is currently playing.
75178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
77178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
78178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_REWINDING          = 5;
79178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
80178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is skipping to the next
81178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    logical chapter (such as a song in a playlist) in the media it is currently playing.
82178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
84178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
85178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_SKIPPING_FORWARDS  = 6;
86178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
87178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is skipping back to the previous
88178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    logical chapter (such as a song in a playlist) in the media it is currently playing.
89178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
91178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
92178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7;
93178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
94178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which is buffering data to play before it can
95178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    start or resume playback.
96178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
98178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
99178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_BUFFERING          = 8;
100178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
101178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Playback state of a RemoteControlClient which cannot perform any playback related
102178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    operation because of an internal error. Examples of such situations are no network
103178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    connectivity when attempting to stream data from a server, or expired user credentials
104178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *    when trying to play subscription-based content.
105178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setPlaybackState(int)
107178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
108178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int PLAYSTATE_ERROR              = 9;
1094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
1104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
1114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The value of a playback state when none has been declared
1124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
1134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int PLAYSTATE_NONE               = 0;
114178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
115178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
116178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "previous" media key.
117178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
119178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS
120178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
121178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0;
122178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
123178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "rewing" media key.
124178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
126178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND
127178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
128178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1;
129178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
130178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "play" media key.
131178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
133178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY
134178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
135178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2;
136178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
137178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "play/pause" media key.
138178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
140178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE
141178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
142178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3;
143178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
144178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "pause" media key.
145178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
147178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE
148178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
149178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4;
150178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
151178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "stop" media key.
152178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
154178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP
155178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
156178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_STOP = 1 << 5;
157178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
158178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "fast forward" media key.
159178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
161178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD
162178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
163178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6;
164178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
165178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag indicating a RemoteControlClient makes use of the "next" media key.
166178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *
1674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see #setTransportControlFlags(int)
168178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT
169178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
170178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7;
171178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
172178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
1734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
1744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The flags for when no media keys are declared supported
1754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
1764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int FLAGS_KEY_MEDIA_NONE = 0;
1774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
1784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
1794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
1804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Flag used to signal some type of metadata exposed by the RemoteControlClient is requested.
181178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
1824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int FLAG_INFORMATION_REQUEST_METADATA = 1 << 0;
183178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
1844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
1854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME doc not valid
186178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag used to signal that the transport control buttons supported by the
187178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * RemoteControlClient have changed.
188178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * This can for instance happen when playback is at the end of a playlist, and the "next"
189178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * operation is not supported anymore.
190178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
1914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int FLAG_INFORMATION_REQUEST_KEY_MEDIA = 1 << 1;
192178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
1934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
1944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME doc not valid
195178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag used to signal that the playback state of the RemoteControlClient has changed.
196178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
1974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int FLAG_INFORMATION_REQUEST_PLAYSTATE = 1 << 2;
198178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
1994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
2004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME doc not valid
201178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     * Flag used to signal that the album art for the RemoteControlClient has changed.
202178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
2034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3;
2044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
2064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Class constructor.
2074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param mediaButtonEventReceiver the receiver for the media button events.
2084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see AudioManager#registerMediaButtonEventReceiver(ComponentName)
2094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see AudioManager#registerRemoteControlClient(RemoteControlClient)
2104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
2114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public RemoteControlClient(ComponentName mediaButtonEventReceiver) {
2124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        mRcEventReceiver = mediaButtonEventReceiver;
2134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        Looper looper;
2154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if ((looper = Looper.myLooper()) != null) {
2164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mEventHandler = new EventHandler(this, looper);
2174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        } else if ((looper = Looper.getMainLooper()) != null) {
2184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mEventHandler = new EventHandler(this, looper);
2194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        } else {
2204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mEventHandler = null;
2214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            Log.e(TAG, "RemoteControlClient() couldn't find main application thread");
2224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
2244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
2264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Class constructor for a remote control client whose internal event handling
2274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * happens on a user-provided Looper.
2284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param mediaButtonEventReceiver the receiver for the media button events.
2294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param looper the Looper running the event loop.
2304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see AudioManager#registerMediaButtonEventReceiver(ComponentName)
2314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see AudioManager#registerRemoteControlClient(RemoteControlClient)
2324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
2334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public RemoteControlClient(ComponentName mediaButtonEventReceiver, Looper looper) {
2344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        mRcEventReceiver = mediaButtonEventReceiver;
2354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        mEventHandler = new EventHandler(this, looper);
2374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
2384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
2404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Class used to modify metadata in a {@link RemoteControlClient} object.
2414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
2424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public class MetadataEditor {
2434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        private MetadataEditor() { /* only use factory */ }
2454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public MetadataEditor putString(int key, String value) {
2474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            return this;
2484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public MetadataEditor putBitmap(int key, Bitmap bitmap) {
2514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            return this;
2524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void clear() {
2554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void apply() {
2594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
2624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public MetadataEditor editMetadata(boolean startEmpty) {
2644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        return (new MetadataEditor());
2654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
2664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
2684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
2694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
2704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME migrate this functionality under MetadataEditor
2714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Start collecting information to be displayed.
2724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Use {@link #commitMetadata()} to signal the end of the collection which has been created
2734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     *  through one or multiple calls to {@link #addMetadataString(int, int, String)}.
2744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
2754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void startMetadata() {
2764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
2774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mMetadata.clear();
2784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
2794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
280178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
281178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
2824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
2834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME migrate this functionality under MetadataEditor
2844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Adds textual information to be displayed.
2854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Note that none of the information added before {@link #startMetadata()},
2864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * and after {@link #commitMetadata()} has been called, will be displayed.
2874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param key the identifier of a the metadata field to set. Valid values are
288178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM},
289178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST},
290178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
291178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST},
292178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR},
293178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER},
294178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION},
295178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER},
296178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE},
297178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER},
298178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION},
299178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE},
300178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
301178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER},
302178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}.
3034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param value the String for the field value, or null to signify there is no valid
3044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     *      information for the field.
305178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
3064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void addMetadataString(int key, String value) {
3074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
3084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // store locally
3094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mMetadata.putString(String.valueOf(key), value);
3104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
3114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
312178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
313178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
3144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
3154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME migrate this functionality under MetadataEditor
3164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Marks all the metadata previously set with {@link #addMetadataString(int, int, String)} as
3174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * eligible to be displayed.
3184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
3194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void commitMetadata() {
3204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
3214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // send to remote control display if conditions are met
3224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            sendMetadata_syncCacheLock();
3234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
3244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
3254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
3264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
3274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
3284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * FIXME migrate this functionality under MetadataEditor
3294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Sets the album / artwork picture to be displayed on the remote control.
3304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param artwork the bitmap for the artwork, or null if there isn't any.
3314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @see android.graphics.Bitmap
3324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
3334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void setArtwork(Bitmap artwork) {
3344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
3354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // resize and store locally
3364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (mArtworkExpectedWidth > 0) {
3374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtwork = scaleBitmapIfTooBig(artwork,
3384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        mArtworkExpectedWidth, mArtworkExpectedHeight);
3394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            } else {
3404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                // no valid resize dimensions, store as is
3414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtwork = artwork;
3424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
3434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // send to remote control display if conditions are met
3444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            sendArtwork_syncCacheLock();
3454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
3464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
3474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
3484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
3494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Sets the current playback state.
3504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param state the current playback state, one of the following values:
351178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_STOPPED},
352178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_PAUSED},
353178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_PLAYING},
354178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_FAST_FORWARDING},
355178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_REWINDING},
356178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_SKIPPING_FORWARDS},
357178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_SKIPPING_BACKWARDS},
358178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_BUFFERING},
359178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *       {@link #PLAYSTATE_ERROR}.
360178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
3614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void setPlaybackState(int state) {
3624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
3634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // store locally
3644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mPlaybackState = state;
3654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
3664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // send to remote control display if conditions are met
3674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            sendPlaybackState_syncCacheLock();
3684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
3694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
370178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
371178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
3724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Sets the flags for the media transport control buttons that this client supports.
3734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param a combination of the following flags:
3744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_PREVIOUS},
375178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_REWIND},
376178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_PLAY},
377178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_PLAY_PAUSE},
378178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_PAUSE},
379178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_STOP},
380178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_FAST_FORWARD},
381178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     *      {@link #FLAG_KEY_MEDIA_NEXT}
382178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
3834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public void setTransportControlFlags(int transportControlFlags) {
3844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
3854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // store locally
3864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mTransportControlFlags = transportControlFlags;
3874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
3884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // send to remote control display if conditions are met
3894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            sendTransportControlFlags_syncCacheLock();
3904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
3914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
392178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi
393178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi    /**
3944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Lock for all cached data
3954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
3964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final Object mCacheLock = new Object();
3974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
3984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Cache for the playback state.
3994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Access synchronized on mCacheLock
400178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi     */
4014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mPlaybackState = PLAYSTATE_NONE;
4024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Cache for the artwork bitmap.
4044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Access synchronized on mCacheLock
4054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private Bitmap mArtwork;
4074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final int ARTWORK_DEFAULT_SIZE = 256;
4084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mArtworkExpectedWidth = ARTWORK_DEFAULT_SIZE;
4094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mArtworkExpectedHeight = ARTWORK_DEFAULT_SIZE;
4104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Cache for the transport control mask.
4124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Access synchronized on mCacheLock
4134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mTransportControlFlags = FLAGS_KEY_MEDIA_NONE;
4154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Cache for the metadata strings.
4174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Access synchronized on mCacheLock
4184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private Bundle mMetadata = new Bundle();
4204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The current remote control client generation ID across the system
4224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mCurrentClientGenId = -1;
4244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The remote control client generation ID, the last time it was told it was the current RC.
4264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * If (mCurrentClientGenId == mInternalClientGenId) is true, it means that this remote control
4274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * client is the "focused" one, and that whenever this client's info is updated, it needs to
4284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * send it to the known IRemoteControlDisplay interfaces.
4294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private int mInternalClientGenId = -2;
4314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The media button event receiver associated with this remote control client
4344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final ComponentName mRcEventReceiver;
4364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The remote control display to which this client will send information.
4394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * NOTE: Only one IRemoteControlDisplay supported in this implementation
4404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private IRemoteControlDisplay mRcDisplay;
4424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
4454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Accessor to media button event receiver
4464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public ComponentName getRcEventReceiver() {
4484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        return mRcEventReceiver;
4494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
4504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @hide
4524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Accessor to IRemoteControlClient
4534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    public IRemoteControlClient getIRemoteControlClient() {
4554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        return mIRCC;
4564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
4574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
4594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * The IRemoteControlClient implementation
4604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
4614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() {
4624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void onInformationRequested(int clientGeneration, int infoFlags,
4644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                int artWidth, int artHeight) {
4654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // only post messages, we can't block here
4664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (mEventHandler != null) {
4674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                // signal new client
4684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_NEW_INTERNAL_CLIENT_GEN);
4694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(
4704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        mEventHandler.obtainMessage(
4714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                                MSG_NEW_INTERNAL_CLIENT_GEN,
4724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                                artWidth, artHeight,
4734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                                new Integer(clientGeneration)));
4744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                // send the information
4754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_REQUEST_PLAYBACK_STATE);
4764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_REQUEST_METADATA);
4774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_REQUEST_TRANSPORTCONTROL);
4784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_REQUEST_ARTWORK);
4794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(
4804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE));
4814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(
4824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL));
4834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA));
4844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(mEventHandler.obtainMessage(MSG_REQUEST_ARTWORK));
4854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
4864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
4874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void setCurrentClientGenerationId(int clientGeneration) {
4894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // only post messages, we can't block here
4904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (mEventHandler != null) {
4914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.removeMessages(MSG_NEW_CURRENT_CLIENT_GEN);
4924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
4934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        MSG_NEW_CURRENT_CLIENT_GEN, clientGeneration, 0/*ignored*/));
4944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
4954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
4964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
4974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void plugRemoteControlDisplay(IRemoteControlDisplay rcd) {
4984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // only post messages, we can't block here
4994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (mEventHandler != null) {
5004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
5014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        MSG_PLUG_DISPLAY, rcd));
5024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
5034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void unplugRemoteControlDisplay(IRemoteControlDisplay rcd) {
5064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // only post messages, we can't block here
5074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (mEventHandler != null) {
5084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
5094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        MSG_UNPLUG_DISPLAY, rcd));
5104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
5114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    };
5134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private EventHandler mEventHandler;
5154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
5164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_REQUEST_METADATA = 2;
5174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_REQUEST_TRANSPORTCONTROL = 3;
5184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_REQUEST_ARTWORK = 4;
5194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_NEW_INTERNAL_CLIENT_GEN = 5;
5204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_NEW_CURRENT_CLIENT_GEN = 6;
5214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_PLUG_DISPLAY = 7;
5224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private final static int MSG_UNPLUG_DISPLAY = 8;
5234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private class EventHandler extends Handler {
5254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public EventHandler(RemoteControlClient rcc, Looper looper) {
5264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            super(looper);
5274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        @Override
5304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        public void handleMessage(Message msg) {
5314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            switch(msg.what) {
5324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_REQUEST_PLAYBACK_STATE:
5334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    synchronized (mCacheLock) {
5344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        sendPlaybackState_syncCacheLock();
5354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    }
5364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_REQUEST_METADATA:
5384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    synchronized (mCacheLock) {
5394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        sendMetadata_syncCacheLock();
5404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    }
5414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_REQUEST_TRANSPORTCONTROL:
5434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    synchronized (mCacheLock) {
5444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        sendTransportControlFlags_syncCacheLock();
5454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    }
5464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_REQUEST_ARTWORK:
5484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    synchronized (mCacheLock) {
5494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        sendArtwork_syncCacheLock();
5504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    }
5514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_NEW_INTERNAL_CLIENT_GEN:
5534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    onNewInternalClientGen((Integer)msg.obj, msg.arg1, msg.arg2);
5544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_NEW_CURRENT_CLIENT_GEN:
5564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    onNewCurrentClientGen(msg.arg1);
5574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_PLUG_DISPLAY:
5594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    onPlugDisplay((IRemoteControlDisplay)msg.obj);
5604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                case MSG_UNPLUG_DISPLAY:
5624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    onUnplugDisplay((IRemoteControlDisplay)msg.obj);
5634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    break;
5644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                default:
5654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler");
5664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
5674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
5694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void sendPlaybackState_syncCacheLock() {
5714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
5724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            try {
5734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay.setPlaybackState(mInternalClientGenId, mPlaybackState);
5744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            } catch (RemoteException e) {
5754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                Log.e(TAG, "Error in setPlaybackState(), dead display "+e);
5764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay = null;
5774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = -1;
5784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = -1;
5794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
5804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
5824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void sendMetadata_syncCacheLock() {
5844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
5854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            try {
5864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
5874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            } catch (RemoteException e) {
5884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                Log.e(TAG, "Error in sendPlaybackState(), dead display "+e);
5894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay = null;
5904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = -1;
5914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = -1;
5924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
5934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
5944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
5954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
5964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void sendTransportControlFlags_syncCacheLock() {
5974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
5984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            try {
5994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay.setTransportControlFlags(mInternalClientGenId,
6004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                        mTransportControlFlags);
6014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            } catch (RemoteException e) {
6024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                Log.e(TAG, "Error in sendTransportControlFlags(), dead display "+e);
6034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay = null;
6044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = -1;
6054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = -1;
6064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
6074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void sendArtwork_syncCacheLock() {
6114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
6124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // even though we have already scaled in setArtwork(), when this client needs to
6134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // send the bitmap, there might be newer and smaller expected dimensions, so we have
6144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // to check again.
6154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mArtwork = scaleBitmapIfTooBig(mArtwork, mArtworkExpectedWidth, mArtworkExpectedHeight);
6164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            try {
6174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay.setArtwork(mInternalClientGenId, mArtwork);
6184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            } catch (RemoteException e) {
6194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                Log.e(TAG, "Error in sendArtwork(), dead display "+e);
6204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay = null;
6214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = -1;
6224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = -1;
6234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
6244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void onNewInternalClientGen(Integer clientGeneration, int artWidth, int artHeight) {
6284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized (mCacheLock) {
6294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // this remote control client is told it is the "focused" one:
6304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            // it implies that now (mCurrentClientGenId == mInternalClientGenId) is true
6314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mInternalClientGenId = clientGeneration.intValue();
6324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if (artWidth > 0) {
6334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = artWidth;
6344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = artHeight;
6354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
6364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void onNewCurrentClientGen(int clientGeneration) {
6404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized (mCacheLock) {
6414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mCurrentClientGenId = clientGeneration;
6424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void onPlugDisplay(IRemoteControlDisplay rcd) {
6464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
6474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            mRcDisplay = rcd;
6484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private void onUnplugDisplay(IRemoteControlDisplay rcd) {
6524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        synchronized(mCacheLock) {
6534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            if ((mRcDisplay != null) && (mRcDisplay.equals(rcd))) {
6544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mRcDisplay = null;
6554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedWidth = ARTWORK_DEFAULT_SIZE;
6564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                mArtworkExpectedHeight = ARTWORK_DEFAULT_SIZE;
6574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            }
6584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
6604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    /**
6624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * Scale a bitmap to fit the smallest dimension by uniformly scaling the incoming bitmap.
6634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * If the bitmap fits, then do nothing and return the original.
6644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     *
6654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param bitmap
6664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param maxWidth
6674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @param maxHeight
6684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     * @return
6694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi     */
6704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    private Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) {
6724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        final int width = bitmap.getWidth();
6734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        final int height = bitmap.getHeight();
6744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        if (width > maxWidth || height > maxHeight) {
6754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            float scale = Math.min((float) maxWidth / width, (float) maxHeight / height);
6764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            int newWidth = Math.round(scale * width);
6774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            int newHeight = Math.round(scale * height);
6784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.getConfig());
6794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            Canvas canvas = new Canvas(outBitmap);
6804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            Paint paint = new Paint();
6814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            paint.setAntiAlias(true);
6824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            paint.setFilterBitmap(true);
6834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            canvas.drawBitmap(bitmap, null,
6844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi                    new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint);
6854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi            bitmap = outBitmap;
6864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        }
6874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi        return bitmap;
6884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi
6894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi    }
690178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi}
691