RemoteControlClient.java revision 5f31737c68f7709cb75a8fefb7536daa77812cc3
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 196e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Triviimport android.app.PendingIntent; 20178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Triviimport android.content.ComponentName; 213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Triviimport android.content.Context; 226e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Triviimport android.content.Intent; 23178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Triviimport android.graphics.Bitmap; 244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.Canvas; 254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.Paint; 264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.graphics.RectF; 27f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErikimport android.media.session.MediaSessionLegacyHelper; 28f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErikimport android.media.session.PlaybackState; 2942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSession; 30f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErikimport android.media.session.TransportPerformer; 314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Bundle; 324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Handler; 333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Triviimport android.os.IBinder; 344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Looper; 354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Message; 364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.RemoteException; 373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Triviimport android.os.ServiceManager; 3868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Triviimport android.os.SystemClock; 394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.util.Log; 404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 415ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Triviimport java.lang.IllegalArgumentException; 424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Triviimport java.util.ArrayList; 434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Triviimport java.util.Iterator; 44178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 45178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi/** 464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * RemoteControlClient enables exposing information meant to be consumed by remote controls 47466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * capable of displaying metadata, artwork and media transport control buttons. 48ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * 49ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <p>A remote control client object is associated with a media button event receiver. This 50466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * event receiver must have been previously registered with 51466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} before the 52466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * RemoteControlClient can be registered through 534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 54ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * 55ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <p>Here is an example of creating a RemoteControlClient instance after registering a media 56ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * button event receiver: 57ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <pre>ComponentName myEventReceiver = new ComponentName(getPackageName(), MyRemoteControlEventReceiver.class.getName()); 58ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * AudioManager myAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 59ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * myAudioManager.registerMediaButtonEventReceiver(myEventReceiver); 60ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * // build the PendingIntent for the remote control client 61ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 62ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * mediaButtonIntent.setComponent(myEventReceiver); 63ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0); 64ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * // create and register the remote control client 65ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * RemoteControlClient myRemoteControlClient = new RemoteControlClient(mediaPendingIntent); 66ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * myAudioManager.registerRemoteControlClient(myRemoteControlClient);</pre> 67178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivipublic class RemoteControlClient 69178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi{ 704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static String TAG = "RemoteControlClient"; 71521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static boolean DEBUG = false; 724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 73178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 74178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is stopped. 75178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 77178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 78178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_STOPPED = 1; 79178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 80178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is paused. 81178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 83178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 84178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_PAUSED = 2; 85178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 86178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is playing media. 87178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 89178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 90178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_PLAYING = 3; 91178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 92178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is fast forwarding in the media 93178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * it is currently playing. 94178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 96178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 97178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_FAST_FORWARDING = 4; 98178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 99178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is fast rewinding in the media 100178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * it is currently playing. 101178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 103178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 104178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_REWINDING = 5; 105178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 106178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is skipping to the next 107178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * logical chapter (such as a song in a playlist) in the media it is currently playing. 108178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 110178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 111178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_SKIPPING_FORWARDS = 6; 112178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 113178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is skipping back to the previous 114178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * logical chapter (such as a song in a playlist) in the media it is currently playing. 115178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 117178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 118178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7; 119178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 120178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is buffering data to play before it can 121178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * start or resume playback. 122178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 124178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 125178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_BUFFERING = 8; 126178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 127178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which cannot perform any playback related 128178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * operation because of an internal error. Examples of such situations are no network 129178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * connectivity when attempting to stream data from a server, or expired user credentials 130178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * when trying to play subscription-based content. 131178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 133178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 134178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_ERROR = 9; 1354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 137466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * The value of a playback state when none has been declared. 138466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Intentionally hidden as an application shouldn't set such a playback state value. 1394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int PLAYSTATE_NONE = 0; 141178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 142178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 1431357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * The default playback type, "local", indicating the presentation of the media is happening on 1453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * the same device (e.g. a phone, a tablet) as where it is controlled from. 1463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_TYPE_LOCAL = 0; 1483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1491357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * A playback type indicating the presentation of the media is happening on 1513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * a different device (i.e. the remote device) than where it is controlled from. 1523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_TYPE_REMOTE = 1; 1543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private final static int PLAYBACK_TYPE_MIN = PLAYBACK_TYPE_LOCAL; 1553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private final static int PLAYBACK_TYPE_MAX = PLAYBACK_TYPE_REMOTE; 1563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1571357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information indicating the playback volume is fixed, i.e. it cannot be controlled 1593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * from this object. An example of fixed playback volume is a remote player, playing over HDMI 1603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * where the user prefer to control the volume on the HDMI sink, rather than attenuate at the 1613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * source. 1623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_VOLUME_FIXED = 0; 1653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1661357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information indicating the playback volume is variable and can be controlled from 1683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this object. 1693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_VOLUME_VARIABLE = 1; 1723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide (to be un-hidden) 1743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * The playback information value indicating the value of a given information type is invalid. 1753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_INVALID_VALUE = Integer.MIN_VALUE; 1783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 179bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 180bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 181bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * An unknown or invalid playback position value. 182bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 183bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static long PLAYBACK_POSITION_INVALID = -1; 184bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 185bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 1861b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi * An invalid playback position value associated with the use of {@link #setPlaybackState(int)} 1871b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi * used to indicate that playback position will remain unknown. 1881b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi */ 1891b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi public final static long PLAYBACK_POSITION_ALWAYS_UNKNOWN = 0x8019771980198300L; 1901b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi /** 1911b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi * @hide 192bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * The default playback speed, 1x. 193bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 194bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static float PLAYBACK_SPEED_1X = 1.0f; 195bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 1963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //========================================== 1973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Public keys for playback information 1983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1991357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines the type of playback associated with this 2013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * RemoteControlClient. See {@link #PLAYBACK_TYPE_LOCAL} and {@link #PLAYBACK_TYPE_REMOTE}. 2023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_PLAYBACK_TYPE = 1; 2043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2051357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines at what volume the playback associated with this 2073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * RemoteControlClient is performed. This information is only used when the playback type is not 2083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}). 2093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME = 2; 2113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2121357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines the maximum volume volume value that is supported 2143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * by the playback associated with this RemoteControlClient. This information is only used 2153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * when the playback type is not local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}). 2163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME_MAX = 3; 2183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2191357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines how volume is handled for the presentation of the media. 2213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACK_VOLUME_FIXED 2223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACK_VOLUME_VARIABLE 2233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME_HANDLING = 4; 2253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2261357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines over what stream type the media is presented. 2283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_USES_STREAM = 5; 2303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 2313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //========================================== 232521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // Public flags for the supported transport control capabilities 2333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 234178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "previous" media key. 235178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 237178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS 238178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 239178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; 240178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 241466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "rewind" media key. 242178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 244178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND 245178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 246178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1; 247178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 248178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "play" media key. 249178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 251178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY 252178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 253178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2; 254178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 255178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "play/pause" media key. 256178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 258178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE 259178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 260178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3; 261178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 262178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "pause" media key. 263178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 265178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE 266178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 267178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4; 268178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 269178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "stop" media key. 270178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 272178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP 273178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 274178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_STOP = 1 << 5; 275178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 276178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "fast forward" media key. 277178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 279178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD 280178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 281178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6; 282178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 283178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "next" media key. 284178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 286178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT 287178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 288178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7; 289bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 290bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag indicating a RemoteControlClient can receive changes in the media playback position 291e63b0609c3b5f6c21d4e006ee9ddd3ba98a4e684Scott Main * through the {@link OnPlaybackPositionUpdateListener} interface. This flag must be set 2923261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * in order for components that display the RemoteControlClient information, to display and 2933261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * let the user control media playback position. 294bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @see #setTransportControlFlags(int) 295915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @see #setOnGetPlaybackPositionListener(OnGetPlaybackPositionListener) 2963261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see #setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener) 297bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 298bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static int FLAG_KEY_MEDIA_POSITION_UPDATE = 1 << 8; 299f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 300f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * Flag indicating a RemoteControlClient supports ratings. 301f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * This flag must be set in order for components that display the RemoteControlClient 302f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * information, to display ratings information, and, if ratings are declared editable 303f841d70155c991b6cf728dd41e6d37e051be453dJean-Michel Trivi * (by calling {@link MediaMetadataEditor#addEditableKey(int)} with the 304f841d70155c991b6cf728dd41e6d37e051be453dJean-Michel Trivi * {@link MediaMetadataEditor#RATING_KEY_BY_USER} key), it will enable the user to rate 305b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * the media, with values being received through the interface set with 306b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * {@link #setMetadataUpdateListener(OnMetadataUpdateListener)}. 307f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * @see #setTransportControlFlags(int) 308f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi */ 309f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi public final static int FLAG_KEY_MEDIA_RATING = 1 << 9; 310178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 311178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 313466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * The flags for when no media keys are declared supported. 314466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Intentionally hidden as an application shouldn't set the transport control flags 315466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * to this value. 3164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 3174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAGS_KEY_MEDIA_NONE = 0; 3184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 3194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 3204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 3214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Flag used to signal some type of metadata exposed by the RemoteControlClient is requested. 322178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_METADATA = 1 << 0; 324178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 326178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag used to signal that the transport control buttons supported by the 327466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * RemoteControlClient are requested. 328178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * This can for instance happen when playback is at the end of a playlist, and the "next" 329178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * operation is not supported anymore. 330178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_KEY_MEDIA = 1 << 1; 332178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 334466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag used to signal that the playback state of the RemoteControlClient is requested. 335178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_PLAYSTATE = 1 << 2; 337178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 339466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag used to signal that the album art for the RemoteControlClient is requested. 340178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3; 3424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 34342ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik private MediaSession mSession; 344f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 3454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 3466e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * Class constructor. 3476e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param mediaButtonIntent The intent that will be sent for the media button events sent 3486e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * by remote controls. 3496e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * This intent needs to have been constructed with the {@link Intent#ACTION_MEDIA_BUTTON} 3506e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * action, and have a component that will handle the intent (set with 3516e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link Intent#setComponent(ComponentName)}) registered with 3526e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} 3536e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * before this new RemoteControlClient can itself be registered with 3546e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 3556e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) 3566e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerRemoteControlClient(RemoteControlClient) 3576e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi */ 3586e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi public RemoteControlClient(PendingIntent mediaButtonIntent) { 359f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mRcMediaIntent = mediaButtonIntent; 3606e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3616e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi Looper looper; 3626e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi if ((looper = Looper.myLooper()) != null) { 3636e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3646e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } else if ((looper = Looper.getMainLooper()) != null) { 3656e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3666e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } else { 3676e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = null; 3686e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi Log.e(TAG, "RemoteControlClient() couldn't find main application thread"); 3696e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3706e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3716e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3726e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi /** 3736e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * Class constructor for a remote control client whose internal event handling 3746e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * happens on a user-provided Looper. 3756e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param mediaButtonIntent The intent that will be sent for the media button events sent 3766e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * by remote controls. 3776e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * This intent needs to have been constructed with the {@link Intent#ACTION_MEDIA_BUTTON} 3786e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * action, and have a component that will handle the intent (set with 3796e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link Intent#setComponent(ComponentName)}) registered with 3806e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} 3816e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * before this new RemoteControlClient can itself be registered with 3826e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 3836e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param looper The Looper running the event loop. 3846e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) 3856e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerRemoteControlClient(RemoteControlClient) 3866e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi */ 3876e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi public RemoteControlClient(PendingIntent mediaButtonIntent, Looper looper) { 388f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mRcMediaIntent = mediaButtonIntent; 3896e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3906e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3916e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3926e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 394f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik * @hide 395f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik */ 396f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik public void registerWithSession(MediaSessionLegacyHelper helper) { 397f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik helper.addRccListener(mRcMediaIntent, mTransportListener); 398f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSession = helper.getSession(mRcMediaIntent); 399f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 400f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 401f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik /** 402f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik * @hide 403f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik */ 404f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik public void unregisterWithSession(MediaSessionLegacyHelper helper) { 405f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik helper.removeRccListener(mRcMediaIntent); 406f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSession = null; 407f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 408f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 409f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik /** 4105f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * Get a {@link MediaSession} associated with this RCC. It will only have a 4115f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * session while it is registered with 4125f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * {@link AudioManager#registerRemoteControlClient}. The session returned 4135f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * should not be modified directly by the application but may be used with 4145f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * other APIs that require a session. 4155f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * 4165f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik * @return A media session object or null. 4175f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik */ 4185f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik public MediaSession getMediaSession() { 4195f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik return mSession; 4205f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik } 4215f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik 4225f31737c68f7709cb75a8fefb7536daa77812cc3RoboErik /** 4234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Class used to modify metadata in a {@link RemoteControlClient} object. 424466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor, 425466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * on which you set the metadata for the RemoteControlClient instance. Once all the information 426466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * has been set, use {@link #apply()} to make it the new metadata that should be displayed 427466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * for the associated client. Once the metadata has been "applied", you cannot reuse this 428466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * instance of the MetadataEditor. 4294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 43088183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi public class MetadataEditor extends MediaMetadataEditor { 4314da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi 4324da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // only use RemoteControlClient.editMetadata() to get a MetadataEditor instance 4334da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi private MetadataEditor() { } 4344da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 4354da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * @hide 4364da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 4374da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public Object clone() throws CloneNotSupportedException { 4384da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi throw new CloneNotSupportedException(); 4394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 4404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 4414da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 4425ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * The metadata key for the content artwork / album art. 4435ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi */ 444466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi public final static int BITMAP_KEY_ARTWORK = 100; 445f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 446f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 447f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * @hide 44888183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * TODO(jmtrivi) have lockscreen move to the new key name and remove 449466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 450466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi public final static int METADATA_KEY_ARTWORK = BITMAP_KEY_ARTWORK; 4515ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi 4525ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi /** 4534da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Adds textual information to be displayed. 4544da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Note that none of the information added after {@link #apply()} has been called, 4554da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * will be displayed. 456466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param key The identifier of a the metadata field to set. Valid values are 4574da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM}, 4584da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}, 4594da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, 4604da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST}, 4614da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR}, 4624da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION}, 4634da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER}, 4644da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE}, 4654da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE}, 4664da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, 467466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}. 468466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param value The text for the given key, or {@code null} to signify there is no valid 4694da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * information for the field. 470466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 471466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 4724da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 4735ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putString(int key, String value) 4745ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 47588183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi super.putString(key, value); 476f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mMetadataBuilder != null) { 477f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // MediaMetadata supports all the same fields as MetadataEditor 478f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key); 479f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // But just in case, don't add things we don't understand 480f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (metadataKey != null) { 481f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mMetadataBuilder.putString(metadataKey, value); 482f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 483f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 484f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 4854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return this; 4864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 4874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 4884da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 489466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Adds numerical information to be displayed. 490466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Note that none of the information added after {@link #apply()} has been called, 491466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * will be displayed. 4925ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @param key the identifier of a the metadata field to set. Valid values are 4935ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, 4945ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, 4955ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value 4965ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * expressed in milliseconds), 49788183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. 498466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param value The long value for the given key 499466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 500466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 5015ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @throws IllegalArgumentException 5024da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 5035ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putLong(int key, long value) 5045ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 50588183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi super.putLong(key, value); 506f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mMetadataBuilder != null) { 507f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // MediaMetadata supports all the same fields as MetadataEditor 508f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key); 509f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // But just in case, don't add things we don't understand 510f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (metadataKey != null) { 511f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mMetadataBuilder.putLong(metadataKey, value); 512f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 513f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 5145ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi return this; 5155ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 5164da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi 5174da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 5184da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Sets the album / artwork picture to be displayed on the remote control. 519466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param key the identifier of the bitmap to set. The only valid value is 520466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link #BITMAP_KEY_ARTWORK} 521466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param bitmap The bitmap for the artwork, or null if there isn't any. 522466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 523466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 5245ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @throws IllegalArgumentException 5254da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * @see android.graphics.Bitmap 5264da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 52788183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi @Override 5285ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap) 5295ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 53088183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi super.putBitmap(key, bitmap); 531f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mMetadataBuilder != null) { 532f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // MediaMetadata supports all the same fields as MetadataEditor 533f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key); 534f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // But just in case, don't add things we don't understand 535f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (metadataKey != null) { 536f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mMetadataBuilder.putBitmap(metadataKey, bitmap); 537f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 538f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 5394da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return this; 5404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 541178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 5424da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 54388183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * Clears all the metadata that has been set since the MetadataEditor instance was created 54488183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * (with {@link RemoteControlClient#editMetadata(boolean)}). 545b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * Note that clearing the metadata doesn't reset the editable keys 54688183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * (use {@link MediaMetadataEditor#removeEditableKeys()} instead). 5474da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 54888183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi @Override 5494da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public synchronized void clear() { 55088183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi super.clear(); 551f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 552f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 553f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 554466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Associates all the metadata that has been set since the MetadataEditor instance was 555466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * created with {@link RemoteControlClient#editMetadata(boolean)}, or since 556466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link #clear()} was called, with the RemoteControlClient. Once "applied", 557466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * this MetadataEditor cannot be reused to edit the RemoteControlClient's metadata. 5584da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 5594da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public synchronized void apply() { 5604da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mApplied) { 5614da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi Log.e(TAG, "Can't apply a previously applied MetadataEditor"); 5624da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return; 5634da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 564f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik synchronized (mCacheLock) { 5654da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // assign the edited data 5664da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mMetadata = new Bundle(mEditorMetadata); 567f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi // add the information about editable keys 568f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi mMetadata.putLong(String.valueOf(KEY_EDITABLE_MASK), mEditableKeys); 5694a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mOriginalArtwork != null) && (!mOriginalArtwork.equals(mEditorArtwork))) { 5704a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mOriginalArtwork.recycle(); 57134d0d300cac645b48cce5a1735f45e1102d4ef0eJean-Michel Trivi } 5724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mOriginalArtwork = mEditorArtwork; 57334d0d300cac645b48cce5a1735f45e1102d4ef0eJean-Michel Trivi mEditorArtwork = null; 5744da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mMetadataChanged & mArtworkChanged) { 5754da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 57686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendMetadataWithArtwork_syncCacheLock(null, 0, 0); 5774da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else if (mMetadataChanged) { 5784da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 57986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendMetadata_syncCacheLock(null); 5804da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else if (mArtworkChanged) { 5814da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 58286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendArtwork_syncCacheLock(null, 0, 0); 5834da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 584f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 585f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // USE_SESSIONS 586f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mSession != null && mMetadataBuilder != null) { 587f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSession.getTransportPerformer().setMetadata(mMetadataBuilder.build()); 588f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 5894da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mApplied = true; 5904da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 5944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 595466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Creates a {@link MetadataEditor}. 596466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param startEmpty Set to false if you want the MetadataEditor to contain the metadata that 597466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * was previously applied to the RemoteControlClient, or true if it is to be created empty. 598466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return a new MetadataEditor instance. 5994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 6004da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public MetadataEditor editMetadata(boolean startEmpty) { 6014da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi MetadataEditor editor = new MetadataEditor(); 6024da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (startEmpty) { 6034da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorMetadata = new Bundle(); 6044da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorArtwork = null; 6054da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mMetadataChanged = true; 6064da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mArtworkChanged = true; 607f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi editor.mEditableKeys = 0; 6084da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else { 6094da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorMetadata = new Bundle(mMetadata); 6104a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi editor.mEditorArtwork = mOriginalArtwork; 6114da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mMetadataChanged = false; 6124da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mArtworkChanged = false; 6134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 614f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // USE_SESSIONS 615f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (startEmpty || mMediaMetadata == null) { 616f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik editor.mMetadataBuilder = new MediaMetadata.Builder(); 617f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } else { 618f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik editor.mMetadataBuilder = new MediaMetadata.Builder(mMediaMetadata); 619f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 6204da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return editor; 6214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 6224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 6234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 6244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Sets the current playback state. 625466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param state The current playback state, one of the following values: 626178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_STOPPED}, 627178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_PAUSED}, 628178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_PLAYING}, 629178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_FAST_FORWARDING}, 630178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_REWINDING}, 631178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_FORWARDS}, 632178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_BACKWARDS}, 633178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_BUFFERING}, 634178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_ERROR}. 635178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 6364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setPlaybackState(int state) { 6371b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi setPlaybackStateInt(state, PLAYBACK_POSITION_ALWAYS_UNKNOWN, PLAYBACK_SPEED_1X, 6381b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi false /* legacy API, converting to method with position and speed */); 639bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 640bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 641bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 642bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Sets the current playback state and the matching media position for the current playback 643bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * speed. 644bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param state The current playback state, one of the following values: 645bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_STOPPED}, 646bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_PAUSED}, 647bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_PLAYING}, 648bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_FAST_FORWARDING}, 649bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_REWINDING}, 650bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_FORWARDS}, 651bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_BACKWARDS}, 652bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_BUFFERING}, 653bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_ERROR}. 654bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param timeInMs a 0 or positive value for the current media position expressed in ms 655bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * (same unit as for when sending the media duration, if applicable, with 656bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} in the 657bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link RemoteControlClient.MetadataEditor}). Negative values imply that position is not 658bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * known (e.g. listening to a live stream of a radio) or not applicable (e.g. when state 659bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * is {@link #PLAYSTATE_BUFFERING} and nothing had played yet). 660bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param playbackSpeed a value expressed as a ratio of 1x playback: 1.0f is normal playback, 661bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * 2.0f is 2x, 0.5f is half-speed, -2.0f is rewind at 2x speed. 0.0f means nothing is 662bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * playing (e.g. when state is {@link #PLAYSTATE_ERROR}). 663bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 664bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public void setPlaybackState(int state, long timeInMs, float playbackSpeed) { 6651b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi setPlaybackStateInt(state, timeInMs, playbackSpeed, true); 6661b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi } 6671b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi 6681b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi private void setPlaybackStateInt(int state, long timeInMs, float playbackSpeed, 6691b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi boolean hasPosition) { 6704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 671bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi if ((mPlaybackState != state) || (mPlaybackPositionMs != timeInMs) 672bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi || (mPlaybackSpeed != playbackSpeed)) { 67368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // store locally 67468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi mPlaybackState = state; 6751b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi // distinguish between an application not knowing the current playback position 6761b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi // at the moment and an application using the API where only the playback state 6771b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi // is passed, not the playback position. 6781b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi if (hasPosition) { 6791b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi if (timeInMs < 0) { 6801b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi mPlaybackPositionMs = PLAYBACK_POSITION_INVALID; 6811b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi } else { 6821b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi mPlaybackPositionMs = timeInMs; 6831b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi } 6841b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi } else { 6851b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi mPlaybackPositionMs = PLAYBACK_POSITION_ALWAYS_UNKNOWN; 6861b16cc3de51d69c8027cefcc70a084a5b2d7a3d0Jean-Michel Trivi } 687bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackSpeed = playbackSpeed; 68868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // keep track of when the state change occurred 68968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime(); 69068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi 69168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // send to remote control display if conditions are met 69286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendPlaybackState_syncCacheLock(null); 6933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // update AudioService 694bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi sendAudioServiceNewPlaybackState_syncCacheLock(); 695521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 696521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // handle automatic playback position refreshes 697c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 698f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 699f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // USE_SESSIONS 700f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mSession != null) { 701f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik int pbState = PlaybackState.getStateFromRccState(state); 702f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSessionPlaybackState.setState(pbState, hasPosition ? 703f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN, 704f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik playbackSpeed); 705f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState); 706f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 707521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 708521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 709521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 710521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 711c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private void initiateCheckForDrift_syncCacheLock() { 712c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (mEventHandler == null) { 713c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 714c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 715c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK); 716c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (!mNeedsPositionSync) { 717c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 718c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 719c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (mPlaybackPositionMs < 0) { 720c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // the current playback state has no known playback position, it's no use 721c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // trying to see if there is any drift at this point 722c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // (this also bypasses this mechanism for older apps that use the old 723c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // setPlaybackState(int) API) 724c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 725c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 726c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (playbackPositionShouldMove(mPlaybackState)) { 727c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // playback position moving, schedule next position drift check 728c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.sendMessageDelayed( 729c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 730c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi getCheckPeriodFromSpeed(mPlaybackSpeed)); 731c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 732c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 733c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 734521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private void onPositionDriftCheck() { 735521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.d(TAG, "onPositionDriftCheck()"); } 736521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi synchronized(mCacheLock) { 737c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mEventHandler == null) || (mPositionProvider == null) || !mNeedsPositionSync) { 738521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return; 739521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 740c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mPlaybackPositionMs < 0) || (mPlaybackSpeed == 0.0f)) { 741c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (DEBUG) { Log.d(TAG, " no valid position or 0 speed, no check needed"); } 742521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return; 743521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 744521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi long estPos = mPlaybackPositionMs + (long) 745521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi ((SystemClock.elapsedRealtime() - mPlaybackStateChangeTimeMs) / mPlaybackSpeed); 746521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi long actPos = mPositionProvider.onGetPlaybackPosition(); 747521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (actPos >= 0) { 748521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (Math.abs(estPos - actPos) > POSITION_DRIFT_MAX_MS) { 749521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // drift happened, report the new position 750521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.w(TAG, " drift detected: actual=" +actPos +" est=" +estPos); } 751521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi setPlaybackState(mPlaybackState, actPos, mPlaybackSpeed); 752521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 753521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.d(TAG, " no drift: actual=" + actPos +" est=" + estPos); } 754521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // no drift, schedule the next drift check 755521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.sendMessageDelayed( 756521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 757521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi getCheckPeriodFromSpeed(mPlaybackSpeed)); 758521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 759521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 760521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // invalid position (negative value), can't check for drift 761521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK); 76268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 7634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 7644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 765178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 766178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 7674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Sets the flags for the media transport control buttons that this client supports. 768466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param transportControlFlags A combination of the following flags: 7694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PREVIOUS}, 770178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_REWIND}, 771178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PLAY}, 772178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PLAY_PAUSE}, 773178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PAUSE}, 774178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_STOP}, 775178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_FAST_FORWARD}, 776915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_NEXT}, 777b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * {@link #FLAG_KEY_MEDIA_POSITION_UPDATE}, 778b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * {@link #FLAG_KEY_MEDIA_RATING}. 779178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 7804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setTransportControlFlags(int transportControlFlags) { 7814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 7824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // store locally 7834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mTransportControlFlags = transportControlFlags; 7844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 7854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // send to remote control display if conditions are met 78686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(null); 787f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 788f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // USE_SESSIONS 789f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mSession != null) { 790f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSessionPlaybackState.setActions(PlaybackState 791f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik .getActionsFromRccControlFlags(transportControlFlags)); 792f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState); 793f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 7944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 7954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 796178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 797bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 798b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * Interface definition for a callback to be invoked when one of the metadata values has 799b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * been updated. 80088183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * Implement this interface to receive metadata updates after registering your listener 80188183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * through {@link RemoteControlClient#setMetadataUpdateListener(OnMetadataUpdateListener)}. 802f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi */ 8037ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public interface OnMetadataUpdateListener { 804f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 805b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * Called on the implementer to notify that the metadata field for the given key has 80688183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * been updated to the new value. 80788183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * @param key the identifier of the updated metadata field. 80888183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi * @param newValue the Object storing the new value for the key. 809f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi */ 81088183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi public abstract void onMetadataUpdate(int key, Object newValue); 811f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 812f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 813f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 814b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * Sets the listener to be called whenever the metadata is updated. 815b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * New metadata values will be received in the same thread as the one in which 816b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * RemoteControlClient was created. 817b23cd118ce3339589fffd40ecf1aa9c5816b3438Jean-Michel Trivi * @param l the metadata update listener 818f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi */ 819f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi public void setMetadataUpdateListener(OnMetadataUpdateListener l) { 820f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi synchronized(mCacheLock) { 821f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi mMetadataUpdateListener = l; 822f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 823f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 824f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 825f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 826f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 827bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Interface definition for a callback to be invoked when the media playback position is 828bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * requested to be updated. 8293261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see RemoteControlClient#FLAG_KEY_MEDIA_POSITION_UPDATE 830bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 831bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public interface OnPlaybackPositionUpdateListener { 832bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 8333261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Called on the implementer to notify it that the playback head should be set at the given 834bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position. If the position can be changed from its current value, the implementor of 8353fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * the interface must also update the playback position using 836e63b0609c3b5f6c21d4e006ee9ddd3ba98a4e684Scott Main * {@link #setPlaybackState(int, long, float)} to reflect the actual new 837bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position being used, regardless of whether it differs from the requested position. 8383fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * Failure to do so would cause the system to not know the new actual playback position, 8393fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * and user interface components would fail to show the user where playback resumed after 8403fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * the position was updated. 841bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param newPositionMs the new requested position in the current media, expressed in ms. 842bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 843bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi void onPlaybackPositionUpdate(long newPositionMs); 844bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 845bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 846bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 8473261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Interface definition for a callback to be invoked when the media playback position is 8483261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * queried. 8493261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see RemoteControlClient#FLAG_KEY_MEDIA_POSITION_UPDATE 8503261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 851915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi public interface OnGetPlaybackPositionListener { 8523261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 8533261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Called on the implementer of the interface to query the current playback position. 8543261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @return a negative value if the current playback position (or the last valid playback 8553261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * position) is not known, or a zero or positive value expressed in ms indicating the 8563261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * current position, or the last valid known position. 8573261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 858915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi long onGetPlaybackPosition(); 8593261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8603261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 8613261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 8623261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Sets the listener to be called whenever the media playback position is requested 863bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * to be updated. 864bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Notifications will be received in the same thread as the one in which RemoteControlClient 865bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * was created. 866915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @param l the position update listener to be called 867bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 868bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener l) { 869bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi synchronized(mCacheLock) { 8703261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi int oldCapa = mPlaybackPositionCapabilities; 8713261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (l != null) { 872bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackPositionCapabilities |= MEDIA_POSITION_WRITABLE; 8733261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } else { 874bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackPositionCapabilities &= ~MEDIA_POSITION_WRITABLE; 875bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 876bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPositionUpdateListener = l; 8773261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (oldCapa != mPlaybackPositionCapabilities) { 8783261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // tell RCDs that this RCC's playback position capabilities have changed 87986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(null); 8803261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8813261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8823261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8833261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 8843261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 8853261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Sets the listener to be called whenever the media current playback position is needed. 8863261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Queries will be received in the same thread as the one in which RemoteControlClient 8873261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * was created. 888915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @param l the listener to be called to retrieve the playback position 8893261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 890915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi public void setOnGetPlaybackPositionListener(OnGetPlaybackPositionListener l) { 8913261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi synchronized(mCacheLock) { 8923261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi int oldCapa = mPlaybackPositionCapabilities; 8933261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (l != null) { 8943261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPlaybackPositionCapabilities |= MEDIA_POSITION_READABLE; 8953261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } else { 8963261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPlaybackPositionCapabilities &= ~MEDIA_POSITION_READABLE; 8973261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8983261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPositionProvider = l; 8993261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (oldCapa != mPlaybackPositionCapabilities) { 9003261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // tell RCDs that this RCC's playback position capabilities have changed 90186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(null); 9023261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 903521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if ((mPositionProvider != null) && (mEventHandler != null) 904521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi && playbackPositionShouldMove(mPlaybackState)) { 905521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // playback position is already moving, but now we have a position provider, 906521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // so schedule a drift check right now 907521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.sendMessageDelayed( 908521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 909521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 0 /*check now*/); 910521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 911bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 912bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 913bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 914bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 915bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 916bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag to reflect that the application controlling this RemoteControlClient sends playback 917bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position updates. The playback position being "readable" is considered from the application's 918bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * point of view. 919bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 920bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public static int MEDIA_POSITION_READABLE = 1 << 0; 921bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 922bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 923bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag to reflect that the application controlling this RemoteControlClient can receive 924bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * playback position updates. The playback position being "writable" 925bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * is considered from the application's point of view. 926bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 927bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public static int MEDIA_POSITION_WRITABLE = 1 << 1; 928bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 929bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private int mPlaybackPositionCapabilities = 0; 930bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 9313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** @hide */ 9323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int DEFAULT_PLAYBACK_VOLUME_HANDLING = PLAYBACK_VOLUME_VARIABLE; 9333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** @hide */ 9343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // hard-coded to the same number of steps as AudioService.MAX_STREAM_VOLUME[STREAM_MUSIC] 9353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int DEFAULT_PLAYBACK_VOLUME = 15; 9363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackType = PLAYBACK_TYPE_LOCAL; 9383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolumeMax = DEFAULT_PLAYBACK_VOLUME; 9393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolume = DEFAULT_PLAYBACK_VOLUME; 9403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolumeHandling = DEFAULT_PLAYBACK_VOLUME_HANDLING; 9413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackStream = AudioManager.STREAM_MUSIC; 9423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 9441357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 9453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Set information describing information related to the playback of media so the system 9463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * can implement additional behavior to handle non-local playback usecases. 9473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param what a key to specify the type of information to set. Valid keys are 9483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_PLAYBACK_TYPE}, 9493114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_USES_STREAM}, 9503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME}, 9513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME_MAX}, 9523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * and {@link #PLAYBACKINFO_VOLUME_HANDLING}. 9533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param value the value for the supplied information to set. 9543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 9553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void setPlaybackInformation(int what, int value) { 9563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized(mCacheLock) { 9573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi switch (what) { 9583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_PLAYBACK_TYPE: 9593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= PLAYBACK_TYPE_MIN) && (value <= PLAYBACK_TYPE_MAX)) { 9603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackType != value) { 9613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackType = value; 9623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 9633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 9653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_PLAYBACK_TYPE"); 9663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME: 9693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value > -1) && (value <= mPlaybackVolumeMax)) { 9703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolume != value) { 9713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolume = value; 9723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 9733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 9753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME"); 9763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_MAX: 9793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (value > 0) { 9803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolumeMax != value) { 9813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolumeMax = value; 9823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 9833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 9853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_MAX"); 9863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_USES_STREAM: 9893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= 0) && (value < AudioSystem.getNumStreamTypes())) { 9903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackStream = value; 9913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 9923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_USES_STREAM"); 9933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_HANDLING: 9963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= PLAYBACK_VOLUME_FIXED) && (value <= PLAYBACK_VOLUME_VARIABLE)) { 9973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolumeHandling != value) { 9983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolumeHandling = value; 9993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 10003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 10023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_HANDLING"); 10033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 10053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi default: 10063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // not throwing an exception or returning an error if more keys are to be 10073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // supported in the future 10083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "setPlaybackInformation() ignoring unknown key " + what); 10093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 10103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 10143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 10151357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 10163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Return playback information represented as an integer value. 10173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param what a key to specify the type of information to retrieve. Valid keys are 10183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_PLAYBACK_TYPE}, 10193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_USES_STREAM}, 10203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME}, 10213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME_MAX}, 10223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * and {@link #PLAYBACKINFO_VOLUME_HANDLING}. 10233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @return the current value for the given information type, or 10243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_INVALID_VALUE} if an error occurred or the request is invalid, or 10253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * the value is unknown. 10263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 10273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public int getIntPlaybackInformation(int what) { 10283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized(mCacheLock) { 10293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi switch (what) { 10303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_PLAYBACK_TYPE: 10313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackType; 10323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME: 10333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolume; 10343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_MAX: 10353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolumeMax; 10363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_USES_STREAM: 10373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackStream; 10383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_HANDLING: 10393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolumeHandling; 10403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi default: 10413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.e(TAG, "getIntPlaybackInformation() unknown key " + what); 10423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return PLAYBACKINFO_INVALID_VALUE; 10433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 10463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 1047178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 10484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Lock for all cached data 10494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final Object mCacheLock = new Object(); 10514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the playback state. 10534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 1054178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 10554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mPlaybackState = PLAYSTATE_NONE; 10564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 105768622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi * Time of last play state change 105868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi * Access synchronized on mCacheLock 105968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi */ 106068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi private long mPlaybackStateChangeTimeMs = 0; 106168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi /** 1062bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Last playback position in ms reported by the user 1063bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 1064bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private long mPlaybackPositionMs = PLAYBACK_POSITION_INVALID; 1065bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 1066bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Last playback speed reported by the user 1067bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 1068bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private float mPlaybackSpeed = PLAYBACK_SPEED_1X; 1069bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 10704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the artwork bitmap. 10714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 10724da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Artwork and metadata are not kept in one Bundle because the bitmap sometimes needs to be 10734da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * accessed to be resized, in which case a copy will be made. This would add overhead in 10744da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Bundle operations. 10754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10764a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private Bitmap mOriginalArtwork; 10774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the transport control mask. 10794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 10804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mTransportControlFlags = FLAGS_KEY_MEDIA_NONE; 10824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the metadata strings. 10844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 108530c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten * This is re-initialized in apply() and so cannot be final. 10864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private Bundle mMetadata = new Bundle(); 10884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1089bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Listener registered by user of RemoteControlClient to receive requests for playback position 1090bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * update requests. 1091bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 1092bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private OnPlaybackPositionUpdateListener mPositionUpdateListener; 1093bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 10943261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Provider registered by user of RemoteControlClient to provide the current playback position. 10953261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 1096915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi private OnGetPlaybackPositionListener mPositionProvider; 10973261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 1098f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * Listener registered by user of RemoteControlClient to receive edit changes to metadata 1099f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi * it exposes. 1100f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi */ 1101f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi private OnMetadataUpdateListener mMetadataUpdateListener; 1102f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi /** 1103bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * The current remote control client generation ID across the system, as known by this object 11044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 11054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mCurrentClientGenId = -1; 11064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 11074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * The remote control client generation ID, the last time it was told it was the current RC. 11084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * If (mCurrentClientGenId == mInternalClientGenId) is true, it means that this remote control 11094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * client is the "focused" one, and that whenever this client's info is updated, it needs to 11104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * send it to the known IRemoteControlDisplay interfaces. 11114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 11124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mInternalClientGenId = -2; 11134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1115f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi * The media button intent description associated with this remote control client 1116bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * (can / should include target component for intent handling, used when persisting media 1117bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * button event receiver across reboots). 11184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1119f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi private final PendingIntent mRcMediaIntent; 11204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1122c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi * Reflects whether any "plugged in" IRemoteControlDisplay has mWantsPositonSync set to true. 1123c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi */ 1124c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // TODO consider using a ref count for IRemoteControlDisplay requiring sync instead 1125c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private boolean mNeedsPositionSync = false; 1126c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 1127c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi /** 1128f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik * Cache for the current playback state using Session APIs. 1129f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik */ 1130f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik private final PlaybackState mSessionPlaybackState = new PlaybackState(); 1131f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 1132f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik /** 1133f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik * Cache for metadata using Session APIs. This is re-initialized in apply(). 1134f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik */ 1135f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik private MediaMetadata mMediaMetadata; 1136f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 1137f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik /** 11384a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * A class to encapsulate all the information about a remote control display. 11394a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay 11404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi */ 11414a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private class DisplayInfoForClient { 11424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** may never be null */ 11434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private IRemoteControlDisplay mRcDisplay; 11444a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private int mArtworkExpectedWidth; 11454a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private int mArtworkExpectedHeight; 1146c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private boolean mWantsPositionSync = false; 1147f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi private boolean mEnabled = true; 11484a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 11494a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi DisplayInfoForClient(IRemoteControlDisplay rcd, int w, int h) { 11504a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mRcDisplay = rcd; 11514a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mArtworkExpectedWidth = w; 11524a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mArtworkExpectedHeight = h; 11534a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 11544a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 11554a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 11564a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** 11574a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * The list of remote control displays to which this client will send information. 11584a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * Accessed and modified synchronized on mCacheLock 11594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 11604a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private ArrayList<DisplayInfoForClient> mRcDisplays = new ArrayList<DisplayInfoForClient>(1); 11614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 11634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 1164f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi * Accessor to media button intent description (includes target component) 11654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1166f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi public PendingIntent getRcMediaIntent() { 1167f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi return mRcMediaIntent; 11684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 11704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 11714426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Accessor to IRemoteControlClient 11724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 11734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public IRemoteControlClient getIRemoteControlClient() { 11744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return mIRCC; 11754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 11784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * The IRemoteControlClient implementation 11794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 118030c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() { 11814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 118286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi //TODO change name to informationRequestForAllDisplays() 11833261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi public void onInformationRequested(int generationId, int infoFlags) { 11844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 11854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi if (mEventHandler != null) { 11864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // signal new client 11874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_NEW_INTERNAL_CLIENT_GEN); 118805e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 11894a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mEventHandler.obtainMessage(MSG_NEW_INTERNAL_CLIENT_GEN, 11903261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /*arg1*/ generationId, /*arg2, ignored*/ 0)); 11914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // send the information 11924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_PLAYBACK_STATE); 11934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_METADATA); 11944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_TRANSPORTCONTROL); 11954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_ARTWORK); 119686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_METADATA_ARTWORK); 119705e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 119886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, null)); 119905e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 120086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, null)); 120186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK, 120286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi 0, 0, null)); 120386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 120486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 120586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi 120686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi public void informationRequestForDisplay(IRemoteControlDisplay rcd, int w, int h) { 120786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // only post messages, we can't block here 120886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (mEventHandler != null) { 120986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.sendMessage( 121086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL, rcd)); 121186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.sendMessage( 121286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE, rcd)); 121386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if ((w > 0) && (h > 0)) { 121486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.sendMessage( 121586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_METADATA_ARTWORK, w, h, rcd)); 121686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } else { 121786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.sendMessage( 121886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_METADATA, rcd)); 121986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 12204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setCurrentClientGenerationId(int clientGeneration) { 12244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 12254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi if (mEventHandler != null) { 12264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_NEW_CURRENT_CLIENT_GEN); 122705e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 12284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi MSG_NEW_CURRENT_CLIENT_GEN, clientGeneration, 0/*ignored*/)); 12294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12324a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi public void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 12334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 12344a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 123505e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 12364a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi MSG_PLUG_DISPLAY, w, h, rcd)); 12374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void unplugRemoteControlDisplay(IRemoteControlDisplay rcd) { 12414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 12424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 124305e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 12444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi MSG_UNPLUG_DISPLAY, rcd)); 12454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12474a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 12484a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi public void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h) { 12494a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // only post messages, we can't block here 12504a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 125105e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 12524a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi MSG_UPDATE_DISPLAY_ARTWORK_SIZE, w, h, rcd)); 12534a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 12544a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 12553261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 1256c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi public void setWantsSyncForDisplay(IRemoteControlDisplay rcd, boolean wantsSync) { 1257c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // only post messages, we can't block here 1258c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 1259c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 1260c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi MSG_DISPLAY_WANTS_POS_SYNC, wantsSync ? 1 : 0, 0/*arg2 ignored*/, rcd)); 1261c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1262c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1263c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 1264f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public void enableRemoteControlDisplay(IRemoteControlDisplay rcd, boolean enabled) { 1265f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi // only post messages, we can't block here 1266f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 1267f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 1268f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi MSG_DISPLAY_ENABLE, enabled ? 1 : 0, 0/*arg2 ignored*/, rcd)); 1269f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1270f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1271f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 12723261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi public void seekTo(int generationId, long timeMs) { 12733261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // only post messages, we can't block here 12743261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (mEventHandler != null) { 12753261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mEventHandler.removeMessages(MSG_SEEK_TO); 127605e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 12773261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi MSG_SEEK_TO, generationId /* arg1 */, 0 /* arg2, ignored */, 12783261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi new Long(timeMs))); 12793261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 12803261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 1281f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 128288183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi public void updateMetadata(int generationId, int key, Rating value) { 1283f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi // only post messages, we can't block here 1284f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi if (mEventHandler != null) { 1285f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 128688183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi MSG_UPDATE_METADATA, generationId /* arg1 */, key /* arg2*/, value)); 1287f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 1288f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 12894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi }; 12904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 12923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide 12933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Default value for the unique identifier 12943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 12953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int RCSE_ID_UNREGISTERED = -1; 12963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 12973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Unique identifier of the RemoteControlStackEntry in AudioService with which 12983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this RemoteControlClient is associated. 12993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 13003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mRcseId = RCSE_ID_UNREGISTERED; 13013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 13023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide 13033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * To be only used by AudioManager after it has received the unique id from 13043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * IAudioService.registerRemoteControlClient() 13053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param id the unique identifier of the RemoteControlStackEntry in AudioService with which 13063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this RemoteControlClient is associated. 13073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 13083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void setRcseId(int id) { 13093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mRcseId = id; 13103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 13113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13121357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi /** 13131357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 13141357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi */ 13151357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi public int getRcseId() { 13161357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi return mRcseId; 13171357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi } 13181357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi 1319f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik // USE_SESSIONS 1320f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik private TransportPerformer.Listener mTransportListener = new TransportPerformer.Listener() { 1321f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 1322f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik @Override 1323f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik public void onSeekTo(long pos) { 1324f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik RemoteControlClient.this.onSeekTo(mCurrentClientGenId, pos); 1325f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 1326f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 1327f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik @Override 1328f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik public void onRate(Rating rating) { 1329f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if ((mTransportControlFlags & FLAG_KEY_MEDIA_RATING) != 0) { 1330f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (mEventHandler != null) { 1331f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik mEventHandler.sendMessage(mEventHandler.obtainMessage( 1332f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik MSG_UPDATE_METADATA, mCurrentClientGenId, 1333f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik MetadataEditor.RATING_KEY_BY_USER, rating)); 1334f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 1335f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 1336f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 1337f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik }; 1338f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 13394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private EventHandler mEventHandler; 13404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_PLAYBACK_STATE = 1; 13414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_METADATA = 2; 13424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_TRANSPORTCONTROL = 3; 13434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_ARTWORK = 4; 13444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_NEW_INTERNAL_CLIENT_GEN = 5; 13454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_NEW_CURRENT_CLIENT_GEN = 6; 13464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_PLUG_DISPLAY = 7; 13474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_UNPLUG_DISPLAY = 8; 13484a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private final static int MSG_UPDATE_DISPLAY_ARTWORK_SIZE = 9; 13493261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi private final static int MSG_SEEK_TO = 10; 1350521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static int MSG_POSITION_DRIFT_CHECK = 11; 1351c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private final static int MSG_DISPLAY_WANTS_POS_SYNC = 12; 135288183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi private final static int MSG_UPDATE_METADATA = 13; 135386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private final static int MSG_REQUEST_METADATA_ARTWORK = 14; 1354f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi private final static int MSG_DISPLAY_ENABLE = 15; 13554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 13564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private class EventHandler extends Handler { 13574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public EventHandler(RemoteControlClient rcc, Looper looper) { 13584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi super(looper); 13594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 13614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi @Override 13624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void handleMessage(Message msg) { 13634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi switch(msg.what) { 13644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_PLAYBACK_STATE: 13654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 136686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendPlaybackState_syncCacheLock((IRemoteControlDisplay)msg.obj); 13674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_METADATA: 13704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 137186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendMetadata_syncCacheLock((IRemoteControlDisplay)msg.obj); 13724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_TRANSPORTCONTROL: 13754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 137686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendTransportControlInfo_syncCacheLock((IRemoteControlDisplay)msg.obj); 13774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_ARTWORK: 13804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 138186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj, 138286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi msg.arg1, msg.arg2); 138386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 138486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi break; 138586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi case MSG_REQUEST_METADATA_ARTWORK: 138686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi synchronized (mCacheLock) { 138786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendMetadataWithArtwork_syncCacheLock((IRemoteControlDisplay)msg.obj, 138886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi msg.arg1, msg.arg2); 13894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_NEW_INTERNAL_CLIENT_GEN: 13924a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onNewInternalClientGen(msg.arg1); 13934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_NEW_CURRENT_CLIENT_GEN: 13954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi onNewCurrentClientGen(msg.arg1); 13964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 13974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_PLUG_DISPLAY: 13984a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onPlugDisplay((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2); 13994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 14004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_UNPLUG_DISPLAY: 14014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi onUnplugDisplay((IRemoteControlDisplay)msg.obj); 14024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 14034a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi case MSG_UPDATE_DISPLAY_ARTWORK_SIZE: 14044a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onUpdateDisplayArtworkSize((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2); 14054a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi break; 14063261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi case MSG_SEEK_TO: 14073261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi onSeekTo(msg.arg1, ((Long)msg.obj).longValue()); 140805e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi break; 1409521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case MSG_POSITION_DRIFT_CHECK: 1410521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi onPositionDriftCheck(); 1411521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi break; 1412c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi case MSG_DISPLAY_WANTS_POS_SYNC: 1413c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi onDisplayWantsSync((IRemoteControlDisplay)msg.obj, msg.arg1 == 1); 1414c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 141588183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi case MSG_UPDATE_METADATA: 141688183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi onUpdateMetadata(msg.arg1, msg.arg2, msg.obj); 1417f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi break; 1418f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi case MSG_DISPLAY_ENABLE: 1419f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi onDisplayEnable((IRemoteControlDisplay)msg.obj, msg.arg1 == 1); 1420f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi break; 14214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi default: 14224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler"); 14234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 14273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 14284a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // Communication with the IRemoteControlDisplay (the displays known to the system) 142944413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi 143086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private void sendPlaybackState_syncCacheLock(IRemoteControlDisplay target) { 14314a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 143286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (target != null) { 143386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi try { 143486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi target.setPlaybackState(mInternalClientGenId, 143586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs, 143686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mPlaybackSpeed); 143786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } catch (RemoteException e) { 143886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi Log.e(TAG, "Error in setPlaybackState() for dead display " + target, e); 143986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 144086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi return; 144186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 144286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // target == null implies all displays must be updated 14434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 14444a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1445f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1446f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1447f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi try { 1448f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mRcDisplay.setPlaybackState(mInternalClientGenId, 1449f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs, 1450f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi mPlaybackSpeed); 1451f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } catch (RemoteException e) { 1452f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi Log.e(TAG, "Error in setPlaybackState(), dead display " + di.mRcDisplay, e); 1453f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi displayIterator.remove(); 1454f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 14554a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 146086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private void sendMetadata_syncCacheLock(IRemoteControlDisplay target) { 14614a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 146286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (target != null) { 146386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi try { 146486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi target.setMetadata(mInternalClientGenId, mMetadata); 146586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } catch (RemoteException e) { 146686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi Log.e(TAG, "Error in setMetadata() for dead display " + target, e); 146786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 146886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi return; 146986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 147086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // target == null implies all displays must be updated 14714a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 14724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1473f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1474f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1475f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi try { 1476f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata); 1477f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } catch (RemoteException e) { 1478f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi Log.e(TAG, "Error in setMetadata(), dead display " + di.mRcDisplay, e); 1479f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi displayIterator.remove(); 1480f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 14814a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 148686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private void sendTransportControlInfo_syncCacheLock(IRemoteControlDisplay target) { 14874a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 148886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (target != null) { 148986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi try { 149086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi target.setTransportControlInfo(mInternalClientGenId, 149186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi mTransportControlFlags, mPlaybackPositionCapabilities); 149286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } catch (RemoteException e) { 149386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi Log.e(TAG, "Error in setTransportControlFlags() for dead display " + target, 149486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi e); 149586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 149686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi return; 149786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 149886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // target == null implies all displays must be updated 14994a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 15004a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1501f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1502f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1503f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi try { 1504f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mRcDisplay.setTransportControlInfo(mInternalClientGenId, 1505f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi mTransportControlFlags, mPlaybackPositionCapabilities); 1506f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } catch (RemoteException e) { 1507f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi Log.e(TAG, "Error in setTransportControlFlags(), dead display " + di.mRcDisplay, 1508f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi e); 1509f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi displayIterator.remove(); 1510f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 15114a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 151686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private void sendArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) { 15174a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // FIXME modify to cache all requested sizes? 15184a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 151986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (target != null) { 152086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi final DisplayInfoForClient di = new DisplayInfoForClient(target, w, h); 152186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi sendArtworkToDisplay(di); 152286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi return; 152386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 152486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // target == null implies all displays must be updated 15254a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 15264a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1527f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (!sendArtworkToDisplay(displayIterator.next())) { 15284a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 15294a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15304a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15314a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15324a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15334a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 15344a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** 15354a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * Send artwork to an IRemoteControlDisplay. 15364a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * @param di encapsulates the IRemoteControlDisplay that will receive the artwork, and its 15374a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * dimension requirements. 15384a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * @return false if there was an error communicating with the IRemoteControlDisplay. 15394a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi */ 15404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private boolean sendArtworkToDisplay(DisplayInfoForClient di) { 15414a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) { 15424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, 15434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth, di.mArtworkExpectedHeight); 15444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi try { 15454a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setArtwork(mInternalClientGenId, artwork); 15464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } catch (RemoteException e) { 15474a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error in sendArtworkToDisplay(), dead display " + di.mRcDisplay, e); 15484a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi return false; 154944413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 155044413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 15514a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi return true; 155244413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 155344413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi 155486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi private void sendMetadataWithArtwork_syncCacheLock(IRemoteControlDisplay target, int w, int h) { 15554a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // FIXME modify to cache all requested sizes? 15564a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 155786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if (target != null) { 155886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi try { 155986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi if ((w > 0) && (h > 0)) { 156086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, w, h); 156186142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi target.setAllMetadata(mInternalClientGenId, mMetadata, artwork); 156286142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } else { 156386142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi target.setMetadata(mInternalClientGenId, mMetadata); 156486142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 156586142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } catch (RemoteException e) { 156686142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi Log.e(TAG, "Error in set(All)Metadata() for dead display " + target, e); 156786142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 156886142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi return; 156986142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi } 157086142da1ce8c1341404a9f9e21be8acbcba69ab3Jean-Michel Trivi // target == null implies all displays must be updated 15714a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 15724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1573f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 15744a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi try { 1575f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1576f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) { 1577f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, 1578f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mArtworkExpectedWidth, di.mArtworkExpectedHeight); 1579f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mRcDisplay.setAllMetadata(mInternalClientGenId, mMetadata, artwork); 1580f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } else { 1581f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata); 1582f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 15834a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15844a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } catch (RemoteException e) { 15854a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error when setting metadata, dead display " + di.mRcDisplay, e); 15864a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 15874a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 15884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 15923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 15933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Communication with AudioService 15943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 15953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static IAudioService sService; 15963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 15973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static IAudioService getService() 15983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi { 15993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (sService != null) { 16003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return sService; 16013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 16023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 16033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sService = IAudioService.Stub.asInterface(b); 16043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return sService; 16053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 16063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 16073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private void sendAudioServiceNewPlaybackInfo_syncCacheLock(int what, int value) { 16083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mRcseId == RCSE_ID_UNREGISTERED) { 16093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return; 16103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 1611f98de1e8dd6dcbd191921b4aa07a1d41b0b9db91Jean-Michel Trivi //Log.d(TAG, "sending to AudioService key=" + what + ", value=" + value); 16123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi IAudioService service = getService(); 16133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi try { 16143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi service.setPlaybackInfoForRcc(mRcseId, what, value); 16153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } catch (RemoteException e) { 1616bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi Log.e(TAG, "Dead object in setPlaybackInfoForRcc", e); 1617bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1618bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1619bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 1620bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private void sendAudioServiceNewPlaybackState_syncCacheLock() { 1621bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi if (mRcseId == RCSE_ID_UNREGISTERED) { 1622bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi return; 1623bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1624bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi IAudioService service = getService(); 1625bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi try { 1626bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi service.setPlaybackStateForRcc(mRcseId, 1627bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackState, mPlaybackPositionMs, mPlaybackSpeed); 1628bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } catch (RemoteException e) { 1629bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi Log.e(TAG, "Dead object in setPlaybackStateForRcc", e); 16303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 16313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 16323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 16333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 16343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Message handlers 16353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 16364a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onNewInternalClientGen(int clientGeneration) { 16374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 16384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // this remote control client is told it is the "focused" one: 16394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // it implies that now (mCurrentClientGenId == mInternalClientGenId) is true 16404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mInternalClientGenId = clientGeneration; 16414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 16444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void onNewCurrentClientGen(int clientGeneration) { 16454426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 16464426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mCurrentClientGenId = clientGeneration; 16474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 16504a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 16514a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onPlugDisplay(IRemoteControlDisplay rcd, int w, int h) { 16524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 16534a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // do we have this display already? 16544a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi boolean displayKnown = false; 16554a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 16564a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext() && !displayKnown) { 1657f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 16584a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder()); 16594a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (displayKnown) { 16604a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // this display was known but the change in artwork size will cause the 16614a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // artwork to be refreshed 16624a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h)) { 16634a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth = w; 16644a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedHeight = h; 16654a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!sendArtworkToDisplay(di)) { 16664a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 16674a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16684a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16694a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16704a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16714a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!displayKnown) { 16724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mRcDisplays.add(new DisplayInfoForClient(rcd, w, h)); 16734a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 16764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 16774a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 16784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void onUnplugDisplay(IRemoteControlDisplay rcd) { 16794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 1680c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 16814a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1682f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 16834a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) { 16844a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 1685c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 1686c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1687c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1688c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // list of RCDs has changed, reevaluate whether position check is still needed 1689c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean oldNeedsPositionSync = mNeedsPositionSync; 1690c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean newNeedsPositionSync = false; 1691c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi displayIterator = mRcDisplays.iterator(); 1692c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi while (displayIterator.hasNext()) { 1693f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1694c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (di.mWantsPositionSync) { 1695c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi newNeedsPositionSync = true; 1696c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 16974a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 16984a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 1699c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mNeedsPositionSync = newNeedsPositionSync; 1700c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (oldNeedsPositionSync != mNeedsPositionSync) { 1701c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // update needed? 1702c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 1703c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 17044a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 17054a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 17064a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 17074a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 17084a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onUpdateDisplayArtworkSize(IRemoteControlDisplay rcd, int w, int h) { 17094a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi synchronized(mCacheLock) { 17104a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 17114a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 1712f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 17134a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) && 17144a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) { 17154a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth = w; 17164a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedHeight = h; 1717f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1718f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (!sendArtworkToDisplay(di)) { 1719f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi displayIterator.remove(); 1720f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 17214a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 17224a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi break; 17234a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 17244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 17254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 17264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 17274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 1728c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi /** pre-condition rcd != null */ 1729c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private void onDisplayWantsSync(IRemoteControlDisplay rcd, boolean wantsSync) { 1730c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi synchronized(mCacheLock) { 1731c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean oldNeedsPositionSync = mNeedsPositionSync; 1732c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean newNeedsPositionSync = false; 1733c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 1734c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // go through the list of RCDs and for each entry, check both whether this is the RCD 1735c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // that gets upated, and whether the list has one entry that wants position sync 1736c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi while (displayIterator.hasNext()) { 1737f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1738f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mEnabled) { 1739f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) { 1740f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mWantsPositionSync = wantsSync; 1741f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1742f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mWantsPositionSync) { 1743f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi newNeedsPositionSync = true; 1744f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1745c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1746c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1747c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mNeedsPositionSync = newNeedsPositionSync; 1748c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (oldNeedsPositionSync != mNeedsPositionSync) { 1749c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // update needed? 1750c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 1751c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1752c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1753c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1754c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 1755f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi /** pre-condition rcd != null */ 1756f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi private void onDisplayEnable(IRemoteControlDisplay rcd, boolean enable) { 1757f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi synchronized(mCacheLock) { 1758f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 1759f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi while (displayIterator.hasNext()) { 1760f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik final DisplayInfoForClient di = displayIterator.next(); 1761f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) { 1762f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi di.mEnabled = enable; 1763f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1764f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1765f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1766f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 1767f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 17683261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi private void onSeekTo(int generationId, long timeMs) { 17693261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi synchronized (mCacheLock) { 17703261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if ((mCurrentClientGenId == generationId) && (mPositionUpdateListener != null)) { 17713261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPositionUpdateListener.onPlaybackPositionUpdate(timeMs); 17723261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 17733261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 17743261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 17753261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 177688183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi private void onUpdateMetadata(int generationId, int key, Object value) { 1777f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi synchronized (mCacheLock) { 1778f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi if ((mCurrentClientGenId == generationId) && (mMetadataUpdateListener != null)) { 177988183e67d4628e8c8a3310af0076b6f33f955cb2Jean-Michel Trivi mMetadataUpdateListener.onMetadataUpdate(key, value); 1780f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 1781f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 1782f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi } 1783f823fc4dba2df5cf5f00e13361f2db93c81f6961Jean-Michel Trivi 17843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 17853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Internal utilities 17863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 17874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 17884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Scale a bitmap to fit the smallest dimension by uniformly scaling the incoming bitmap. 17894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * If the bitmap fits, then do nothing and return the original. 17904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * 17914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param bitmap 17924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param maxWidth 17934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param maxHeight 17944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @return 17954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 17964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 17974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) { 17986e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi if (bitmap != null) { 17996e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi final int width = bitmap.getWidth(); 18006e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi final int height = bitmap.getHeight(); 18016e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi if (width > maxWidth || height > maxHeight) { 18026e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi float scale = Math.min((float) maxWidth / width, (float) maxHeight / height); 18036e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi int newWidth = Math.round(scale * width); 18046e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi int newHeight = Math.round(scale * height); 180505c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich Bitmap.Config newConfig = bitmap.getConfig(); 180605c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich if (newConfig == null) { 180705c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich newConfig = Bitmap.Config.ARGB_8888; 180805c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich } 180905c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, newConfig); 18106e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi Canvas canvas = new Canvas(outBitmap); 18116e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi Paint paint = new Paint(); 18126e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi paint.setAntiAlias(true); 18136e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi paint.setFilterBitmap(true); 18146e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi canvas.drawBitmap(bitmap, null, 18156e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint); 18166e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi bitmap = outBitmap; 18176e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi } 18184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 18194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return bitmap; 18205ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 18214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 1822521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 1823521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1824521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Returns whether, for the given playback state, the playback position is expected to 1825521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * be changing. 1826521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @param playstate the playback state to evaluate 1827521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @return true during any form of playback, false if it's not playing anything while in this 1828521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * playback state 1829521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1830f8895248e2ac4dbb46622f3e04c7256f03175b4fAdam Powell static boolean playbackPositionShouldMove(int playstate) { 1831521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi switch(playstate) { 1832521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_STOPPED: 1833521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_PAUSED: 1834521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_BUFFERING: 1835521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_ERROR: 1836521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_SKIPPING_FORWARDS: 1837521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_SKIPPING_BACKWARDS: 1838521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return false; 1839521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_PLAYING: 1840521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_FAST_FORWARDING: 1841521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_REWINDING: 1842521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi default: 1843521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return true; 1844521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1845521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1846521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 1847521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1848521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Period for playback position drift checks, 15s when playing at 1x or slower. 1849521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1850521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_REFRESH_PERIOD_PLAYING_MS = 15000; 1851521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1852521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Minimum period for playback position drift checks, never more often when every 2s, when 1853521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * fast forwarding or rewinding. 1854521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1855521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_REFRESH_PERIOD_MIN_MS = 2000; 1856521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1857521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * The value above which the difference between client-reported playback position and 1858521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * estimated position is considered a drift. 1859521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1860521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_DRIFT_MAX_MS = 500; 1861521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1862521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Compute the period at which the estimated playback position should be compared against the 1863521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * actual playback position. Is a funciton of playback speed. 1864521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @param speed 1.0f is normal playback speed 1865521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @return the period in ms 1866521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1867521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private static long getCheckPeriodFromSpeed(float speed) { 1868521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (Math.abs(speed) <= 1.0f) { 1869521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return POSITION_REFRESH_PERIOD_PLAYING_MS; 1870521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 1871521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return Math.max((long)(POSITION_REFRESH_PERIOD_PLAYING_MS / Math.abs(speed)), 1872521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi POSITION_REFRESH_PERIOD_MIN_MS); 1873521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1874521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1875178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi} 1876