RemoteControlClient.java revision c3c4babf8424f65b3d3d2700f60fae6e94e9cd00
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; 275ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Triviimport android.media.MediaMetadataRetriever; 284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Bundle; 294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Handler; 303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Triviimport android.os.IBinder; 314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Looper; 324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.Message; 334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.os.RemoteException; 343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Triviimport android.os.ServiceManager; 3568622396b62f9084781add1e12f4d513b633ab54Jean-Michel Triviimport android.os.SystemClock; 364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Triviimport android.util.Log; 374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 385ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Triviimport java.lang.IllegalArgumentException; 394a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Triviimport java.util.ArrayList; 404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Triviimport java.util.Iterator; 41178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 42178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi/** 434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * RemoteControlClient enables exposing information meant to be consumed by remote controls 44466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * capable of displaying metadata, artwork and media transport control buttons. 45ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * 46ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <p>A remote control client object is associated with a media button event receiver. This 47466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * event receiver must have been previously registered with 48466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} before the 49466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * RemoteControlClient can be registered through 504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 51ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * 52ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <p>Here is an example of creating a RemoteControlClient instance after registering a media 53ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * button event receiver: 54ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * <pre>ComponentName myEventReceiver = new ComponentName(getPackageName(), MyRemoteControlEventReceiver.class.getName()); 55ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * AudioManager myAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 56ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * myAudioManager.registerMediaButtonEventReceiver(myEventReceiver); 57ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * // build the PendingIntent for the remote control client 58ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 59ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * mediaButtonIntent.setComponent(myEventReceiver); 60ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0); 61ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * // create and register the remote control client 62ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * RemoteControlClient myRemoteControlClient = new RemoteControlClient(mediaPendingIntent); 63ad87f5b40f2a3fd2d506dc15e00b8af28a8fa2baJean-Michel Trivi * myAudioManager.registerRemoteControlClient(myRemoteControlClient);</pre> 64178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivipublic class RemoteControlClient 66178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi{ 674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static String TAG = "RemoteControlClient"; 68521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static boolean DEBUG = false; 694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 70178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 71178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is stopped. 72178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 74178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 75178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_STOPPED = 1; 76178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 77178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is paused. 78178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 80178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 81178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_PAUSED = 2; 82178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 83178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is playing media. 84178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 86178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 87178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_PLAYING = 3; 88178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 89178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is fast forwarding in the media 90178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * it is currently playing. 91178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 93178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 94178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_FAST_FORWARDING = 4; 95178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 96178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is fast rewinding in the media 97178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * it is currently playing. 98178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 100178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 101178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_REWINDING = 5; 102178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 103178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is skipping to the next 104178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * logical chapter (such as a song in a playlist) in the media it is currently playing. 105178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 107178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 108178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_SKIPPING_FORWARDS = 6; 109178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 110178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is skipping back to the previous 111178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * logical chapter (such as a song in a playlist) in the media it is currently playing. 112178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 114178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 115178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7; 116178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 117178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which is buffering data to play before it can 118178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * start or resume playback. 119178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 121178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 122178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_BUFFERING = 8; 123178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 124178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Playback state of a RemoteControlClient which cannot perform any playback related 125178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * operation because of an internal error. Examples of such situations are no network 126178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * connectivity when attempting to stream data from a server, or expired user credentials 127178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * when trying to play subscription-based content. 128178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 1294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setPlaybackState(int) 130178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 131178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int PLAYSTATE_ERROR = 9; 1324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 134466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * The value of a playback state when none has been declared. 135466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Intentionally hidden as an application shouldn't set such a playback state value. 1364426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int PLAYSTATE_NONE = 0; 138178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 139178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 1401357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * The default playback type, "local", indicating the presentation of the media is happening on 1423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * the same device (e.g. a phone, a tablet) as where it is controlled from. 1433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_TYPE_LOCAL = 0; 1453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1461357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * A playback type indicating the presentation of the media is happening on 1483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * a different device (i.e. the remote device) than where it is controlled from. 1493114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_TYPE_REMOTE = 1; 1513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private final static int PLAYBACK_TYPE_MIN = PLAYBACK_TYPE_LOCAL; 1523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private final static int PLAYBACK_TYPE_MAX = PLAYBACK_TYPE_REMOTE; 1533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1541357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information indicating the playback volume is fixed, i.e. it cannot be controlled 1563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * from this object. An example of fixed playback volume is a remote player, playing over HDMI 1573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * where the user prefer to control the volume on the HDMI sink, rather than attenuate at the 1583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * source. 1593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_VOLUME_FIXED = 0; 1623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1631357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information indicating the playback volume is variable and can be controlled from 1653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this object. 1663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACK_VOLUME_VARIABLE = 1; 1693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide (to be un-hidden) 1713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * The playback information value indicating the value of a given information type is invalid. 1723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACKINFO_VOLUME_HANDLING. 1733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_INVALID_VALUE = Integer.MIN_VALUE; 1753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 176bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 177bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 178bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * An unknown or invalid playback position value. 179bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 180bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static long PLAYBACK_POSITION_INVALID = -1; 181bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 182bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 183bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * The default playback speed, 1x. 184bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 185bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static float PLAYBACK_SPEED_1X = 1.0f; 186bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 1873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //========================================== 1883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Public keys for playback information 1893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1901357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines the type of playback associated with this 1923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * RemoteControlClient. See {@link #PLAYBACK_TYPE_LOCAL} and {@link #PLAYBACK_TYPE_REMOTE}. 1933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 1943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_PLAYBACK_TYPE = 1; 1953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 1961357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 1973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines at what volume the playback associated with this 1983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * RemoteControlClient is performed. This information is only used when the playback type is not 1993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}). 2003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME = 2; 2023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2031357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines the maximum volume volume value that is supported 2053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * by the playback associated with this RemoteControlClient. This information is only used 2063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * when the playback type is not local (see {@link #PLAYBACKINFO_PLAYBACK_TYPE}). 2073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME_MAX = 3; 2093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2101357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines how volume is handled for the presentation of the media. 2123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACK_VOLUME_FIXED 2133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @see #PLAYBACK_VOLUME_VARIABLE 2143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_VOLUME_HANDLING = 4; 2163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 2171357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 2183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Playback information that defines over what stream type the media is presented. 2193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 2203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int PLAYBACKINFO_USES_STREAM = 5; 2213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 2223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //========================================== 223521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // Public flags for the supported transport control capabilities 2243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 225178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "previous" media key. 226178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 228178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS 229178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 230178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0; 231178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 232466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "rewind" media key. 233178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 235178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND 236178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 237178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1; 238178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 239178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "play" media key. 240178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 242178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY 243178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 244178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2; 245178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 246178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "play/pause" media key. 247178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 249178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE 250178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 251178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3; 252178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 253178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "pause" media key. 254178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 256178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE 257178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 258178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4; 259178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 260178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "stop" media key. 261178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 263178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP 264178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 265178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_STOP = 1 << 5; 266178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 267178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "fast forward" media key. 268178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 270178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD 271178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 272178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6; 273178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 274178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag indicating a RemoteControlClient makes use of the "next" media key. 275178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * 2764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @see #setTransportControlFlags(int) 277178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT 278178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 279178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7; 280bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 281bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag indicating a RemoteControlClient can receive changes in the media playback position 282e63b0609c3b5f6c21d4e006ee9ddd3ba98a4e684Scott Main * through the {@link OnPlaybackPositionUpdateListener} interface. This flag must be set 2833261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * in order for components that display the RemoteControlClient information, to display and 2843261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * let the user control media playback position. 285bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @see #setTransportControlFlags(int) 286915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @see #setOnGetPlaybackPositionListener(OnGetPlaybackPositionListener) 2873261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see #setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener) 288bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 289bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public final static int FLAG_KEY_MEDIA_POSITION_UPDATE = 1 << 8; 290178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 291178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 2924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 293466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * The flags for when no media keys are declared supported. 294466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Intentionally hidden as an application shouldn't set the transport control flags 295466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * to this value. 2964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 2974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAGS_KEY_MEDIA_NONE = 0; 2984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 2994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 3004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 3014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Flag used to signal some type of metadata exposed by the RemoteControlClient is requested. 302178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_METADATA = 1 << 0; 304178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 306178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * Flag used to signal that the transport control buttons supported by the 307466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * RemoteControlClient are requested. 308178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * This can for instance happen when playback is at the end of a playlist, and the "next" 309178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * operation is not supported anymore. 310178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_KEY_MEDIA = 1 << 1; 312178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 314466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag used to signal that the playback state of the RemoteControlClient is requested. 315178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_PLAYSTATE = 1 << 2; 317178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 3184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 319466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Flag used to signal that the album art for the RemoteControlClient is requested. 320178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 3214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3; 3224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 3234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 3246e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * Class constructor. 3256e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param mediaButtonIntent The intent that will be sent for the media button events sent 3266e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * by remote controls. 3276e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * This intent needs to have been constructed with the {@link Intent#ACTION_MEDIA_BUTTON} 3286e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * action, and have a component that will handle the intent (set with 3296e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link Intent#setComponent(ComponentName)}) registered with 3306e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} 3316e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * before this new RemoteControlClient can itself be registered with 3326e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 3336e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) 3346e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerRemoteControlClient(RemoteControlClient) 3356e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi */ 3366e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi public RemoteControlClient(PendingIntent mediaButtonIntent) { 337f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mRcMediaIntent = mediaButtonIntent; 3386e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3396e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi Looper looper; 3406e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi if ((looper = Looper.myLooper()) != null) { 3416e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3426e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } else if ((looper = Looper.getMainLooper()) != null) { 3436e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3446e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } else { 3456e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = null; 3466e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi Log.e(TAG, "RemoteControlClient() couldn't find main application thread"); 3476e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3486e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3496e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3506e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi /** 3516e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * Class constructor for a remote control client whose internal event handling 3526e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * happens on a user-provided Looper. 3536e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param mediaButtonIntent The intent that will be sent for the media button events sent 3546e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * by remote controls. 3556e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * This intent needs to have been constructed with the {@link Intent#ACTION_MEDIA_BUTTON} 3566e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * action, and have a component that will handle the intent (set with 3576e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link Intent#setComponent(ComponentName)}) registered with 3586e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerMediaButtonEventReceiver(ComponentName)} 3596e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * before this new RemoteControlClient can itself be registered with 3606e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * {@link AudioManager#registerRemoteControlClient(RemoteControlClient)}. 3616e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @param looper The Looper running the event loop. 3626e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerMediaButtonEventReceiver(ComponentName) 3636e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi * @see AudioManager#registerRemoteControlClient(RemoteControlClient) 3646e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi */ 3656e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi public RemoteControlClient(PendingIntent mediaButtonIntent, Looper looper) { 366f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mRcMediaIntent = mediaButtonIntent; 3676e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3686e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi mEventHandler = new EventHandler(this, looper); 3696e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi } 3706e920e6dac11c3ebf6c0c19402934834e9e491bfJean-Michel Trivi 3715ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi private static final int[] METADATA_KEYS_TYPE_STRING = { 3725ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_ALBUM, 3735ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, 3745ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_TITLE, 3755ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_ARTIST, 3765ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_AUTHOR, 3775ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_COMPILATION, 3785ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_COMPOSER, 3795ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_DATE, 3805ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_GENRE, 3815ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_TITLE, 3825ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_WRITER }; 3835ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi private static final int[] METADATA_KEYS_TYPE_LONG = { 3845ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, 3855ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER, 3865ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi MediaMetadataRetriever.METADATA_KEY_DURATION }; 3875ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi 3884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 3894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Class used to modify metadata in a {@link RemoteControlClient} object. 390466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor, 391466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * on which you set the metadata for the RemoteControlClient instance. Once all the information 392466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * has been set, use {@link #apply()} to make it the new metadata that should be displayed 393466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * for the associated client. Once the metadata has been "applied", you cannot reuse this 394466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * instance of the MetadataEditor. 3954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 3964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public class MetadataEditor { 397466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi /** 398466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @hide 399466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 4004da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi protected boolean mMetadataChanged; 401466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi /** 402466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @hide 403466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 4044da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi protected boolean mArtworkChanged; 405466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi /** 406466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @hide 407466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 4084da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi protected Bitmap mEditorArtwork; 409466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi /** 410466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @hide 411466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 4124da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi protected Bundle mEditorMetadata; 4134da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi private boolean mApplied = false; 4144da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi 4154da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // only use RemoteControlClient.editMetadata() to get a MetadataEditor instance 4164da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi private MetadataEditor() { } 4174da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 4184da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * @hide 4194da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 4204da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public Object clone() throws CloneNotSupportedException { 4214da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi throw new CloneNotSupportedException(); 4224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 4234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 4244da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 4255ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * The metadata key for the content artwork / album art. 4265ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi */ 427466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi public final static int BITMAP_KEY_ARTWORK = 100; 428466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi /** 429466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @hide 430466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * TODO(jmtrivi) have lockscreen and music move to the new key name 431466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi */ 432466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi public final static int METADATA_KEY_ARTWORK = BITMAP_KEY_ARTWORK; 4335ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi 4345ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi /** 4354da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Adds textual information to be displayed. 4364da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Note that none of the information added after {@link #apply()} has been called, 4374da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * will be displayed. 438466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param key The identifier of a the metadata field to set. Valid values are 4394da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM}, 4404da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}, 4414da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, 4424da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST}, 4434da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR}, 4444da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION}, 4454da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER}, 4464da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE}, 4474da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE}, 4484da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE}, 449466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}. 450466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param value The text for the given key, or {@code null} to signify there is no valid 4514da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * information for the field. 452466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 453466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 4544da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 4555ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putString(int key, String value) 4565ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 4574da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mApplied) { 4584da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi Log.e(TAG, "Can't edit a previously applied MetadataEditor"); 4594da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return this; 4604da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 4615ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi if (!validTypeForKey(key, METADATA_KEYS_TYPE_STRING)) { 4625ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throw(new IllegalArgumentException("Invalid type 'String' for key "+ key)); 4635ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 4644da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mEditorMetadata.putString(String.valueOf(key), value); 4654da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mMetadataChanged = true; 4664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return this; 4674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 4684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 4694da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 470466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Adds numerical information to be displayed. 471466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Note that none of the information added after {@link #apply()} has been called, 472466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * will be displayed. 4735ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @param key the identifier of a the metadata field to set. Valid values are 4745ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER}, 4755ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}, 4765ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value 4775ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * expressed in milliseconds), 4785ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}. 479466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param value The long value for the given key 480466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 481466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 4825ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @throws IllegalArgumentException 4834da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 4845ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putLong(int key, long value) 4855ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 4865ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi if (mApplied) { 4875ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi Log.e(TAG, "Can't edit a previously applied MetadataEditor"); 4885ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi return this; 4895ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 4905ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi if (!validTypeForKey(key, METADATA_KEYS_TYPE_LONG)) { 4915ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throw(new IllegalArgumentException("Invalid type 'long' for key "+ key)); 4925ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 4935ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi mEditorMetadata.putLong(String.valueOf(key), value); 4945ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi mMetadataChanged = true; 4955ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi return this; 4965ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 4974da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi 4984da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 4994da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Sets the album / artwork picture to be displayed on the remote control. 500466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param key the identifier of the bitmap to set. The only valid value is 501466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link #BITMAP_KEY_ARTWORK} 502466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param bitmap The bitmap for the artwork, or null if there isn't any. 503466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return Returns a reference to the same MetadataEditor object, so you can chain put 504466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * calls together. 5055ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @throws IllegalArgumentException 5064da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * @see android.graphics.Bitmap 5074da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 5085ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap) 5095ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throws IllegalArgumentException { 5104da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mApplied) { 5114da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi Log.e(TAG, "Can't edit a previously applied MetadataEditor"); 5124da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return this; 5134da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 514466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi if (key != BITMAP_KEY_ARTWORK) { 5155ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key)); 5164da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5174a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mEditorArtwork = bitmap; 5184da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mArtworkChanged = true; 5194da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return this; 5204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 521178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 5224da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 523466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Clears all the metadata that has been set since the MetadataEditor instance was 524466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * created with {@link RemoteControlClient#editMetadata(boolean)}. 5254da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 5264da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public synchronized void clear() { 5274da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mApplied) { 5284da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi Log.e(TAG, "Can't clear a previously applied MetadataEditor"); 5294da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return; 5304da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5314da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mEditorMetadata.clear(); 5324da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mEditorArtwork = null; 5334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 534178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 5354da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi /** 536466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Associates all the metadata that has been set since the MetadataEditor instance was 537466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * created with {@link RemoteControlClient#editMetadata(boolean)}, or since 538466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * {@link #clear()} was called, with the RemoteControlClient. Once "applied", 539466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * this MetadataEditor cannot be reused to edit the RemoteControlClient's metadata. 5404da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi */ 5414da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public synchronized void apply() { 5424da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mApplied) { 5434da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi Log.e(TAG, "Can't apply a previously applied MetadataEditor"); 5444da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return; 5454da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5464da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi synchronized(mCacheLock) { 5474da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // assign the edited data 5484da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mMetadata = new Bundle(mEditorMetadata); 5494a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mOriginalArtwork != null) && (!mOriginalArtwork.equals(mEditorArtwork))) { 5504a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mOriginalArtwork.recycle(); 55134d0d300cac645b48cce5a1735f45e1102d4ef0eJean-Michel Trivi } 5524a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mOriginalArtwork = mEditorArtwork; 55334d0d300cac645b48cce5a1735f45e1102d4ef0eJean-Michel Trivi mEditorArtwork = null; 5544da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (mMetadataChanged & mArtworkChanged) { 5554da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 55644413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi sendMetadataWithArtwork_syncCacheLock(); 5574da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else if (mMetadataChanged) { 5584da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 5594da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi sendMetadata_syncCacheLock(); 5604da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else if (mArtworkChanged) { 5614da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi // send to remote control display if conditions are met 5624da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi sendArtwork_syncCacheLock(); 5634da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5644da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi mApplied = true; 5654da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } 5664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 5694426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 570466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * Creates a {@link MetadataEditor}. 571466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param startEmpty Set to false if you want the MetadataEditor to contain the metadata that 572466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * was previously applied to the RemoteControlClient, or true if it is to be created empty. 573466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @return a new MetadataEditor instance. 5744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 5754da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi public MetadataEditor editMetadata(boolean startEmpty) { 5764da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi MetadataEditor editor = new MetadataEditor(); 5774da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi if (startEmpty) { 5784da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorMetadata = new Bundle(); 5794da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorArtwork = null; 5804da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mMetadataChanged = true; 5814da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mArtworkChanged = true; 5824da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi } else { 5834da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mEditorMetadata = new Bundle(mMetadata); 5844a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi editor.mEditorArtwork = mOriginalArtwork; 5854da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mMetadataChanged = false; 5864da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi editor.mArtworkChanged = false; 5874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5884da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi return editor; 5894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 5904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 5914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 5924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Sets the current playback state. 593466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param state The current playback state, one of the following values: 594178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_STOPPED}, 595178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_PAUSED}, 596178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_PLAYING}, 597178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_FAST_FORWARDING}, 598178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_REWINDING}, 599178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_FORWARDS}, 600178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_BACKWARDS}, 601178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_BUFFERING}, 602178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #PLAYSTATE_ERROR}. 603178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 6044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setPlaybackState(int state) { 605bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi setPlaybackState(state, PLAYBACK_POSITION_INVALID, PLAYBACK_SPEED_1X); 606bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 607bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 608bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 609bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Sets the current playback state and the matching media position for the current playback 610bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * speed. 611bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param state The current playback state, one of the following values: 612bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_STOPPED}, 613bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_PAUSED}, 614bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_PLAYING}, 615bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_FAST_FORWARDING}, 616bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_REWINDING}, 617bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_FORWARDS}, 618bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_SKIPPING_BACKWARDS}, 619bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_BUFFERING}, 620bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link #PLAYSTATE_ERROR}. 621bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param timeInMs a 0 or positive value for the current media position expressed in ms 622bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * (same unit as for when sending the media duration, if applicable, with 623bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} in the 624bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * {@link RemoteControlClient.MetadataEditor}). Negative values imply that position is not 625bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * known (e.g. listening to a live stream of a radio) or not applicable (e.g. when state 626bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * is {@link #PLAYSTATE_BUFFERING} and nothing had played yet). 627bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param playbackSpeed a value expressed as a ratio of 1x playback: 1.0f is normal playback, 628bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * 2.0f is 2x, 0.5f is half-speed, -2.0f is rewind at 2x speed. 0.0f means nothing is 629bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * playing (e.g. when state is {@link #PLAYSTATE_ERROR}). 630bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 631bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public void setPlaybackState(int state, long timeInMs, float playbackSpeed) { 6324426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 633bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi if ((mPlaybackState != state) || (mPlaybackPositionMs != timeInMs) 634bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi || (mPlaybackSpeed != playbackSpeed)) { 63568622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // store locally 63668622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi mPlaybackState = state; 637bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackPositionMs = timeInMs; 638bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackSpeed = playbackSpeed; 63968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // keep track of when the state change occurred 64068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi mPlaybackStateChangeTimeMs = SystemClock.elapsedRealtime(); 64168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi 64268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // send to remote control display if conditions are met 64368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi sendPlaybackState_syncCacheLock(); 6443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // update AudioService 645bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi sendAudioServiceNewPlaybackState_syncCacheLock(); 646521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 647521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // handle automatic playback position refreshes 648c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 649521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 650521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 651521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 652521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 653c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private void initiateCheckForDrift_syncCacheLock() { 654c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (mEventHandler == null) { 655c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 656c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 657c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK); 658c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (!mNeedsPositionSync) { 659c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 660c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 661c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (mPlaybackPositionMs < 0) { 662c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // the current playback state has no known playback position, it's no use 663c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // trying to see if there is any drift at this point 664c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // (this also bypasses this mechanism for older apps that use the old 665c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // setPlaybackState(int) API) 666c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi return; 667c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 668c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (playbackPositionShouldMove(mPlaybackState)) { 669c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // playback position moving, schedule next position drift check 670c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.sendMessageDelayed( 671c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 672c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi getCheckPeriodFromSpeed(mPlaybackSpeed)); 673c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 674c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 675c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 676521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private void onPositionDriftCheck() { 677521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.d(TAG, "onPositionDriftCheck()"); } 678521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi synchronized(mCacheLock) { 679c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mEventHandler == null) || (mPositionProvider == null) || !mNeedsPositionSync) { 680521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return; 681521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 682c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mPlaybackPositionMs < 0) || (mPlaybackSpeed == 0.0f)) { 683c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (DEBUG) { Log.d(TAG, " no valid position or 0 speed, no check needed"); } 684521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return; 685521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 686521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi long estPos = mPlaybackPositionMs + (long) 687521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi ((SystemClock.elapsedRealtime() - mPlaybackStateChangeTimeMs) / mPlaybackSpeed); 688521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi long actPos = mPositionProvider.onGetPlaybackPosition(); 689521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (actPos >= 0) { 690521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (Math.abs(estPos - actPos) > POSITION_DRIFT_MAX_MS) { 691521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // drift happened, report the new position 692521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.w(TAG, " drift detected: actual=" +actPos +" est=" +estPos); } 693521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi setPlaybackState(mPlaybackState, actPos, mPlaybackSpeed); 694521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 695521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (DEBUG) { Log.d(TAG, " no drift: actual=" + actPos +" est=" + estPos); } 696521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // no drift, schedule the next drift check 697521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.sendMessageDelayed( 698521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 699521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi getCheckPeriodFromSpeed(mPlaybackSpeed)); 700521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 701521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 702521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // invalid position (negative value), can't check for drift 703521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK); 70468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 7054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 7064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 707178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 708178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 7094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Sets the flags for the media transport control buttons that this client supports. 710466ade5ad66e7bfb1814d5e5ac76a17f8a0bcd3aJean-Michel Trivi * @param transportControlFlags A combination of the following flags: 7114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PREVIOUS}, 712178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_REWIND}, 713178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PLAY}, 714178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PLAY_PAUSE}, 715178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_PAUSE}, 716178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_STOP}, 717178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_FAST_FORWARD}, 718915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_NEXT}, 719915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * {@link #FLAG_KEY_MEDIA_POSITION_UPDATE} 720178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 7214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setTransportControlFlags(int transportControlFlags) { 7224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 7234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // store locally 7244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mTransportControlFlags = transportControlFlags; 7254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 7264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // send to remote control display if conditions are met 7273261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(); 7284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 7294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 730178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi 731bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 732bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Interface definition for a callback to be invoked when the media playback position is 733bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * requested to be updated. 7343261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see RemoteControlClient#FLAG_KEY_MEDIA_POSITION_UPDATE 735bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 736bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public interface OnPlaybackPositionUpdateListener { 737bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 7383261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Called on the implementer to notify it that the playback head should be set at the given 739bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position. If the position can be changed from its current value, the implementor of 7403fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * the interface must also update the playback position using 741e63b0609c3b5f6c21d4e006ee9ddd3ba98a4e684Scott Main * {@link #setPlaybackState(int, long, float)} to reflect the actual new 742bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position being used, regardless of whether it differs from the requested position. 7433fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * Failure to do so would cause the system to not know the new actual playback position, 7443fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * and user interface components would fail to show the user where playback resumed after 7453fbf67e217fb489fe7318a9e43d8ae86646eb4ccJean-Michel Trivi * the position was updated. 746bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @param newPositionMs the new requested position in the current media, expressed in ms. 747bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 748bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi void onPlaybackPositionUpdate(long newPositionMs); 749bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 750bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 751bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 7523261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Interface definition for a callback to be invoked when the media playback position is 7533261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * queried. 7543261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @see RemoteControlClient#FLAG_KEY_MEDIA_POSITION_UPDATE 7553261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 756915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi public interface OnGetPlaybackPositionListener { 7573261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 7583261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Called on the implementer of the interface to query the current playback position. 7593261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * @return a negative value if the current playback position (or the last valid playback 7603261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * position) is not known, or a zero or positive value expressed in ms indicating the 7613261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * current position, or the last valid known position. 7623261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 763915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi long onGetPlaybackPosition(); 7643261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 7653261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 7663261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 7673261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Sets the listener to be called whenever the media playback position is requested 768bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * to be updated. 769bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Notifications will be received in the same thread as the one in which RemoteControlClient 770bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * was created. 771915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @param l the position update listener to be called 772bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 773bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener l) { 774bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi synchronized(mCacheLock) { 7753261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi int oldCapa = mPlaybackPositionCapabilities; 7763261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (l != null) { 777bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackPositionCapabilities |= MEDIA_POSITION_WRITABLE; 7783261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } else { 779bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackPositionCapabilities &= ~MEDIA_POSITION_WRITABLE; 780bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 781bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPositionUpdateListener = l; 7823261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (oldCapa != mPlaybackPositionCapabilities) { 7833261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // tell RCDs that this RCC's playback position capabilities have changed 7843261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(); 7853261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 7863261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 7873261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 7883261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 7893261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 7903261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Sets the listener to be called whenever the media current playback position is needed. 7913261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Queries will be received in the same thread as the one in which RemoteControlClient 7923261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * was created. 793915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi * @param l the listener to be called to retrieve the playback position 7943261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 795915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi public void setOnGetPlaybackPositionListener(OnGetPlaybackPositionListener l) { 7963261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi synchronized(mCacheLock) { 7973261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi int oldCapa = mPlaybackPositionCapabilities; 7983261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (l != null) { 7993261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPlaybackPositionCapabilities |= MEDIA_POSITION_READABLE; 8003261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } else { 8013261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPlaybackPositionCapabilities &= ~MEDIA_POSITION_READABLE; 8023261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 8033261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPositionProvider = l; 8043261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (oldCapa != mPlaybackPositionCapabilities) { 8053261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // tell RCDs that this RCC's playback position capabilities have changed 8063261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(); 8073261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 808521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if ((mPositionProvider != null) && (mEventHandler != null) 809521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi && playbackPositionShouldMove(mPlaybackState)) { 810521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // playback position is already moving, but now we have a position provider, 811521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi // so schedule a drift check right now 812521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.sendMessageDelayed( 813521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK), 814521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 0 /*check now*/); 815521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 816bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 817bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 818bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 819bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 820bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 821bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag to reflect that the application controlling this RemoteControlClient sends playback 822bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * position updates. The playback position being "readable" is considered from the application's 823bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * point of view. 824bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 825bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public static int MEDIA_POSITION_READABLE = 1 << 0; 826bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 827bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * @hide 828bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Flag to reflect that the application controlling this RemoteControlClient can receive 829bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * playback position updates. The playback position being "writable" 830bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * is considered from the application's point of view. 831bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 832bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public static int MEDIA_POSITION_WRITABLE = 1 << 1; 833bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 834bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private int mPlaybackPositionCapabilities = 0; 835bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 8363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** @hide */ 8373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int DEFAULT_PLAYBACK_VOLUME_HANDLING = PLAYBACK_VOLUME_VARIABLE; 8383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** @hide */ 8393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // hard-coded to the same number of steps as AudioService.MAX_STREAM_VOLUME[STREAM_MUSIC] 8403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int DEFAULT_PLAYBACK_VOLUME = 15; 8413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackType = PLAYBACK_TYPE_LOCAL; 8433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolumeMax = DEFAULT_PLAYBACK_VOLUME; 8443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolume = DEFAULT_PLAYBACK_VOLUME; 8453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackVolumeHandling = DEFAULT_PLAYBACK_VOLUME_HANDLING; 8463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mPlaybackStream = AudioManager.STREAM_MUSIC; 8473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 8491357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 8503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Set information describing information related to the playback of media so the system 8513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * can implement additional behavior to handle non-local playback usecases. 8523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param what a key to specify the type of information to set. Valid keys are 8533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_PLAYBACK_TYPE}, 8543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_USES_STREAM}, 8553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME}, 8563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME_MAX}, 8573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * and {@link #PLAYBACKINFO_VOLUME_HANDLING}. 8583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param value the value for the supplied information to set. 8593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 8603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void setPlaybackInformation(int what, int value) { 8613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized(mCacheLock) { 8623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi switch (what) { 8633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_PLAYBACK_TYPE: 8643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= PLAYBACK_TYPE_MIN) && (value <= PLAYBACK_TYPE_MAX)) { 8653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackType != value) { 8663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackType = value; 8673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 8683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 8703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_PLAYBACK_TYPE"); 8713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 8733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME: 8743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value > -1) && (value <= mPlaybackVolumeMax)) { 8753114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolume != value) { 8763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolume = value; 8773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 8783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 8803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME"); 8813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 8833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_MAX: 8843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (value > 0) { 8853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolumeMax != value) { 8863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolumeMax = value; 8873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 8883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 8903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_MAX"); 8913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 8933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_USES_STREAM: 8943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= 0) && (value < AudioSystem.getNumStreamTypes())) { 8953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackStream = value; 8963114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 8973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_USES_STREAM"); 8983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8993114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_HANDLING: 9013114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((value >= PLAYBACK_VOLUME_FIXED) && (value <= PLAYBACK_VOLUME_VARIABLE)) { 9023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mPlaybackVolumeHandling != value) { 9033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mPlaybackVolumeHandling = value; 9043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sendAudioServiceNewPlaybackInfo_syncCacheLock(what, value); 9053114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 9073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "using invalid value for PLAYBACKINFO_VOLUME_HANDLING"); 9083114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi default: 9113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // not throwing an exception or returning an error if more keys are to be 9123114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // supported in the future 9133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.w(TAG, "setPlaybackInformation() ignoring unknown key " + what); 9143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi break; 9153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 9193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 9201357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 9213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Return playback information represented as an integer value. 9223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param what a key to specify the type of information to retrieve. Valid keys are 9233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_PLAYBACK_TYPE}, 9243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_USES_STREAM}, 9253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME}, 9263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_VOLUME_MAX}, 9273114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * and {@link #PLAYBACKINFO_VOLUME_HANDLING}. 9283114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @return the current value for the given information type, or 9293114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * {@link #PLAYBACKINFO_INVALID_VALUE} if an error occurred or the request is invalid, or 9303114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * the value is unknown. 9313114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 9323114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public int getIntPlaybackInformation(int what) { 9333114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi synchronized(mCacheLock) { 9343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi switch (what) { 9353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_PLAYBACK_TYPE: 9363114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackType; 9373114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME: 9383114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolume; 9393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_MAX: 9403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolumeMax; 9413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_USES_STREAM: 9423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackStream; 9433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi case PLAYBACKINFO_VOLUME_HANDLING: 9443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return mPlaybackVolumeHandling; 9453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi default: 9463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.e(TAG, "getIntPlaybackInformation() unknown key " + what); 9473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return PLAYBACKINFO_INVALID_VALUE; 9483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9493114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 9513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 952178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi /** 9534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Lock for all cached data 9544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 9554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final Object mCacheLock = new Object(); 9564426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 9574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the playback state. 9584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 959178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi */ 9604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mPlaybackState = PLAYSTATE_NONE; 9614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 96268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi * Time of last play state change 96368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi * Access synchronized on mCacheLock 96468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi */ 96568622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi private long mPlaybackStateChangeTimeMs = 0; 96668622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi /** 967bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Last playback position in ms reported by the user 968bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 969bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private long mPlaybackPositionMs = PLAYBACK_POSITION_INVALID; 970bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 971bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Last playback speed reported by the user 972bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 973bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private float mPlaybackSpeed = PLAYBACK_SPEED_1X; 974bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 9754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the artwork bitmap. 9764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 9774da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Artwork and metadata are not kept in one Bundle because the bitmap sometimes needs to be 9784da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * accessed to be resized, in which case a copy will be made. This would add overhead in 9794da5eeffc92331b958eeb111aa2f3d938083954eJean-Michel Trivi * Bundle operations. 9804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 9814a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private Bitmap mOriginalArtwork; 9824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 9834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the transport control mask. 9844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 9854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 9864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mTransportControlFlags = FLAGS_KEY_MEDIA_NONE; 9874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 9884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Cache for the metadata strings. 9894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Access synchronized on mCacheLock 99030c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten * This is re-initialized in apply() and so cannot be final. 9914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 9924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private Bundle mMetadata = new Bundle(); 9934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 994bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * Listener registered by user of RemoteControlClient to receive requests for playback position 995bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * update requests. 996bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi */ 997bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private OnPlaybackPositionUpdateListener mPositionUpdateListener; 998bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi /** 9993261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi * Provider registered by user of RemoteControlClient to provide the current playback position. 10003261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi */ 1001915747730060dff71b5b2ca7e4ee4073024fc24eJean-Michel Trivi private OnGetPlaybackPositionListener mPositionProvider; 10023261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /** 1003bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * The current remote control client generation ID across the system, as known by this object 10044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mCurrentClientGenId = -1; 10064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * The remote control client generation ID, the last time it was told it was the current RC. 10084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * If (mCurrentClientGenId == mInternalClientGenId) is true, it means that this remote control 10094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * client is the "focused" one, and that whenever this client's info is updated, it needs to 10104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * send it to the known IRemoteControlDisplay interfaces. 10114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private int mInternalClientGenId = -2; 10134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1015f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi * The media button intent description associated with this remote control client 1016bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * (can / should include target component for intent handling, used when persisting media 1017bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi * button event receiver across reboots). 10184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1019f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi private final PendingIntent mRcMediaIntent; 10204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 1022c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi * Reflects whether any "plugged in" IRemoteControlDisplay has mWantsPositonSync set to true. 1023c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi */ 1024c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // TODO consider using a ref count for IRemoteControlDisplay requiring sync instead 1025c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private boolean mNeedsPositionSync = false; 1026c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 1027c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi /** 10284a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * A class to encapsulate all the information about a remote control display. 10294a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay 10304a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi */ 10314a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private class DisplayInfoForClient { 10324a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** may never be null */ 10334a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private IRemoteControlDisplay mRcDisplay; 10344a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private int mArtworkExpectedWidth; 10354a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private int mArtworkExpectedHeight; 1036c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private boolean mWantsPositionSync = false; 10374a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 10384a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi DisplayInfoForClient(IRemoteControlDisplay rcd, int w, int h) { 10394a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mRcDisplay = rcd; 10404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mArtworkExpectedWidth = w; 10414a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mArtworkExpectedHeight = h; 10424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 10434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 10444a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 10454a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** 10464a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * The list of remote control displays to which this client will send information. 10474a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * Accessed and modified synchronized on mCacheLock 10484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10494a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private ArrayList<DisplayInfoForClient> mRcDisplays = new ArrayList<DisplayInfoForClient>(1); 10504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10514426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 1053f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi * Accessor to media button intent description (includes target component) 10544426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 1055f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi public PendingIntent getRcMediaIntent() { 1056f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi return mRcMediaIntent; 10574426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 10584426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10594426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @hide 10604426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Accessor to IRemoteControlClient 10614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 10624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public IRemoteControlClient getIRemoteControlClient() { 10634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return mIRCC; 10644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 10654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10664426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 10674426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * The IRemoteControlClient implementation 10684426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 106930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() { 10704426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10713261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi public void onInformationRequested(int generationId, int infoFlags) { 10724426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 10734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi if (mEventHandler != null) { 10744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // signal new client 10754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_NEW_INTERNAL_CLIENT_GEN); 107605e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 10774a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mEventHandler.obtainMessage(MSG_NEW_INTERNAL_CLIENT_GEN, 10783261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi /*arg1*/ generationId, /*arg2, ignored*/ 0)); 10794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // send the information 10804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_PLAYBACK_STATE); 10814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_METADATA); 10824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_TRANSPORTCONTROL); 10834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_REQUEST_ARTWORK); 108405e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 10854426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_PLAYBACK_STATE)); 108605e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage( 10874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.obtainMessage(MSG_REQUEST_TRANSPORTCONTROL)); 108805e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_METADATA)); 108905e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage(MSG_REQUEST_ARTWORK)); 10904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 10914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 10924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 10934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void setCurrentClientGenerationId(int clientGeneration) { 10944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 10954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi if (mEventHandler != null) { 10964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mEventHandler.removeMessages(MSG_NEW_CURRENT_CLIENT_GEN); 109705e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 10984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi MSG_NEW_CURRENT_CLIENT_GEN, clientGeneration, 0/*ignored*/)); 10994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11024a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi public void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 11034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 11044a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 110505e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 11064a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi MSG_PLUG_DISPLAY, w, h, rcd)); 11074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void unplugRemoteControlDisplay(IRemoteControlDisplay rcd) { 11114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // only post messages, we can't block here 11124a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 111305e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 11144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi MSG_UNPLUG_DISPLAY, rcd)); 11154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11164426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11174a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 11184a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi public void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h) { 11194a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // only post messages, we can't block here 11204a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 112105e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 11224a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi MSG_UPDATE_DISPLAY_ARTWORK_SIZE, w, h, rcd)); 11234a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 11244a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 11253261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 1126c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi public void setWantsSyncForDisplay(IRemoteControlDisplay rcd, boolean wantsSync) { 1127c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // only post messages, we can't block here 1128c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if ((mEventHandler != null) && (rcd != null)) { 1129c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 1130c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi MSG_DISPLAY_WANTS_POS_SYNC, wantsSync ? 1 : 0, 0/*arg2 ignored*/, rcd)); 1131c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1132c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1133c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 11343261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi public void seekTo(int generationId, long timeMs) { 11353261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi // only post messages, we can't block here 11363261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if (mEventHandler != null) { 11373261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mEventHandler.removeMessages(MSG_SEEK_TO); 113805e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi mEventHandler.sendMessage(mEventHandler.obtainMessage( 11393261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi MSG_SEEK_TO, generationId /* arg1 */, 0 /* arg2, ignored */, 11403261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi new Long(timeMs))); 11413261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 11423261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 11434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi }; 11444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 11463114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide 11473114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Default value for the unique identifier 11483114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 11493114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int RCSE_ID_UNREGISTERED = -1; 11503114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 11513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * Unique identifier of the RemoteControlStackEntry in AudioService with which 11523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this RemoteControlClient is associated. 11533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 11543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private int mRcseId = RCSE_ID_UNREGISTERED; 11553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 11563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @hide 11573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * To be only used by AudioManager after it has received the unique id from 11583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * IAudioService.registerRemoteControlClient() 11593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * @param id the unique identifier of the RemoteControlStackEntry in AudioService with which 11603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * this RemoteControlClient is associated. 11613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 11623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public void setRcseId(int id) { 11633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi mRcseId = id; 11643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 11653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 11661357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi /** 11671357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi * @hide 11681357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi */ 11691357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi public int getRcseId() { 11701357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi return mRcseId; 11711357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi } 11721357012968f9066ea3051d83995e9bac69526c3cJean-Michel Trivi 11734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private EventHandler mEventHandler; 11744426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_PLAYBACK_STATE = 1; 11754426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_METADATA = 2; 11764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_TRANSPORTCONTROL = 3; 11774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_REQUEST_ARTWORK = 4; 11784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_NEW_INTERNAL_CLIENT_GEN = 5; 11794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_NEW_CURRENT_CLIENT_GEN = 6; 11804426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_PLUG_DISPLAY = 7; 11814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private final static int MSG_UNPLUG_DISPLAY = 8; 11824a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private final static int MSG_UPDATE_DISPLAY_ARTWORK_SIZE = 9; 11833261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi private final static int MSG_SEEK_TO = 10; 1184521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static int MSG_POSITION_DRIFT_CHECK = 11; 1185c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private final static int MSG_DISPLAY_WANTS_POS_SYNC = 12; 11864426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11874426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private class EventHandler extends Handler { 11884426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public EventHandler(RemoteControlClient rcc, Looper looper) { 11894426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi super(looper); 11904426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11914426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 11924426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi @Override 11934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi public void handleMessage(Message msg) { 11944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi switch(msg.what) { 11954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_PLAYBACK_STATE: 11964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 11974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi sendPlaybackState_syncCacheLock(); 11984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 11994426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_METADATA: 12014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 12024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi sendMetadata_syncCacheLock(); 12034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_TRANSPORTCONTROL: 12064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 12073261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi sendTransportControlInfo_syncCacheLock(); 12084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12094426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12104426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_REQUEST_ARTWORK: 12114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 12124426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi sendArtwork_syncCacheLock(); 12134426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12144426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12154426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_NEW_INTERNAL_CLIENT_GEN: 12164a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onNewInternalClientGen(msg.arg1); 12174426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12184426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_NEW_CURRENT_CLIENT_GEN: 12194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi onNewCurrentClientGen(msg.arg1); 12204426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_PLUG_DISPLAY: 12224a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onPlugDisplay((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2); 12234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi case MSG_UNPLUG_DISPLAY: 12254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi onUnplugDisplay((IRemoteControlDisplay)msg.obj); 12264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi break; 12274a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi case MSG_UPDATE_DISPLAY_ARTWORK_SIZE: 12284a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi onUpdateDisplayArtworkSize((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2); 12294a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi break; 12303261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi case MSG_SEEK_TO: 12313261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi onSeekTo(msg.arg1, ((Long)msg.obj).longValue()); 123205e7c2ff8cd6b6386d8c553995c2d12075833e4aJean-Michel Trivi break; 1233521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case MSG_POSITION_DRIFT_CHECK: 1234521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi onPositionDriftCheck(); 1235521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi break; 1236c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi case MSG_DISPLAY_WANTS_POS_SYNC: 1237c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi onDisplayWantsSync((IRemoteControlDisplay)msg.obj, msg.arg1 == 1); 1238c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 12394426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi default: 12404426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler"); 12414426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12424426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12434426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12444426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 12464a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // Communication with the IRemoteControlDisplay (the displays known to the system) 124744413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi 12484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void sendPlaybackState_syncCacheLock() { 12494a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 12504a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 12514a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 12524a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 12534a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi try { 12544a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setPlaybackState(mInternalClientGenId, 1255bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackState, mPlaybackStateChangeTimeMs, mPlaybackPositionMs, 1256bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackSpeed); 12574a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } catch (RemoteException e) { 12584a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error in setPlaybackState(), dead display " + di.mRcDisplay, e); 12594a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 12604a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 12614426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12624426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12634426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12644426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12654426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void sendMetadata_syncCacheLock() { 12664a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 12674a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 12684a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 12694a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 12704a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi try { 12714a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata); 12724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } catch (RemoteException e) { 12734a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error in setMetadata(), dead display " + di.mRcDisplay, e); 12744a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 12754a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 12764426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12774426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12784426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12794426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12803261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi private void sendTransportControlInfo_syncCacheLock() { 12814a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 12824a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 12834a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 12844a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 12854a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi try { 12863261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi di.mRcDisplay.setTransportControlInfo(mInternalClientGenId, 12873261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mTransportControlFlags, mPlaybackPositionCapabilities); 12884a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } catch (RemoteException e) { 12894a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error in setTransportControlFlags(), dead display " + di.mRcDisplay, 12904a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi e); 12914a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 12924a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 12934426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12944426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12954426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 12964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 12974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void sendArtwork_syncCacheLock() { 12984a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // FIXME modify to cache all requested sizes? 12994a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 13004a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 13014a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 13024a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!sendArtworkToDisplay((DisplayInfoForClient) displayIterator.next())) { 13034a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 13044a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13054a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13064a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13074a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13084a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 13094a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** 13104a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * Send artwork to an IRemoteControlDisplay. 13114a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * @param di encapsulates the IRemoteControlDisplay that will receive the artwork, and its 13124a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * dimension requirements. 13134a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi * @return false if there was an error communicating with the IRemoteControlDisplay. 13144a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi */ 13154a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private boolean sendArtworkToDisplay(DisplayInfoForClient di) { 13164a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) { 13174a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, 13184a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth, di.mArtworkExpectedHeight); 13194426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi try { 13204a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setArtwork(mInternalClientGenId, artwork); 13214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } catch (RemoteException e) { 13224a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error in sendArtworkToDisplay(), dead display " + di.mRcDisplay, e); 13234a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi return false; 132444413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 132544413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 13264a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi return true; 132744413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi } 132844413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi 132944413e5b514a91806a4bb4c7780029ea43be6f81Jean-Michel Trivi private void sendMetadataWithArtwork_syncCacheLock() { 13304a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // FIXME modify to cache all requested sizes? 13314a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (mCurrentClientGenId == mInternalClientGenId) { 13324a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 13334a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 13344a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 13354a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi try { 13364a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) { 13374a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork, 13384a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth, di.mArtworkExpectedHeight); 13394a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setAllMetadata(mInternalClientGenId, mMetadata, artwork); 13404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } else { 13414a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata); 13424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } catch (RemoteException e) { 13444a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi Log.e(TAG, "Error when setting metadata, dead display " + di.mRcDisplay, e); 13454a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 13464a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 13474426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13484426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13494426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 13504426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 13513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 13523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Communication with AudioService 13533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static IAudioService sService; 13553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private static IAudioService getService() 13573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi { 13583114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (sService != null) { 13593114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return sService; 13603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 13613114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 13623114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi sService = IAudioService.Stub.asInterface(b); 13633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return sService; 13643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 13653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi private void sendAudioServiceNewPlaybackInfo_syncCacheLock(int what, int value) { 13673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (mRcseId == RCSE_ID_UNREGISTERED) { 13683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return; 13693114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 1370f98de1e8dd6dcbd191921b4aa07a1d41b0b9db91Jean-Michel Trivi //Log.d(TAG, "sending to AudioService key=" + what + ", value=" + value); 13713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi IAudioService service = getService(); 13723114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi try { 13733114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi service.setPlaybackInfoForRcc(mRcseId, what, value); 13743114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } catch (RemoteException e) { 1375bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi Log.e(TAG, "Dead object in setPlaybackInfoForRcc", e); 1376bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1377bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1378bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi 1379bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi private void sendAudioServiceNewPlaybackState_syncCacheLock() { 1380bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi if (mRcseId == RCSE_ID_UNREGISTERED) { 1381bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi return; 1382bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } 1383bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi IAudioService service = getService(); 1384bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi try { 1385bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi service.setPlaybackStateForRcc(mRcseId, 1386bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi mPlaybackState, mPlaybackPositionMs, mPlaybackSpeed); 1387bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi } catch (RemoteException e) { 1388bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi Log.e(TAG, "Dead object in setPlaybackStateForRcc", e); 13893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 13903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 13913114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 13933114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Message handlers 13943114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 13954a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onNewInternalClientGen(int clientGeneration) { 13964426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 13974426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // this remote control client is told it is the "focused" one: 13984426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi // it implies that now (mCurrentClientGenId == mInternalClientGenId) is true 13994a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mInternalClientGenId = clientGeneration; 14004426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14014426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14024426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 14034426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void onNewCurrentClientGen(int clientGeneration) { 14044426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized (mCacheLock) { 14054426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi mCurrentClientGenId = clientGeneration; 14064426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14074426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14084426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 14094a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 14104a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onPlugDisplay(IRemoteControlDisplay rcd, int w, int h) { 14114426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 14124a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // do we have this display already? 14134a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi boolean displayKnown = false; 14144a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 14154a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext() && !displayKnown) { 14164a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 14174a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder()); 14184a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (displayKnown) { 14194a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // this display was known but the change in artwork size will cause the 14204a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi // artwork to be refreshed 14214a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h)) { 14224a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth = w; 14234a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedHeight = h; 14244a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!sendArtworkToDisplay(di)) { 14254a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 14264a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14274a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14284a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14294a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14304a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!displayKnown) { 14314a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi mRcDisplays.add(new DisplayInfoForClient(rcd, w, h)); 14324a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14334426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14344426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14354426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 14364a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 14374426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private void onUnplugDisplay(IRemoteControlDisplay rcd) { 14384426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi synchronized(mCacheLock) { 1439c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 14404a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 14414a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 14424a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) { 14434a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 1444c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 1445c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1446c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1447c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // list of RCDs has changed, reevaluate whether position check is still needed 1448c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean oldNeedsPositionSync = mNeedsPositionSync; 1449c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean newNeedsPositionSync = false; 1450c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi displayIterator = mRcDisplays.iterator(); 1451c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi while (displayIterator.hasNext()) { 1452c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 1453c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (di.mWantsPositionSync) { 1454c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi newNeedsPositionSync = true; 1455c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi break; 14564a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14574a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 1458c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mNeedsPositionSync = newNeedsPositionSync; 1459c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (oldNeedsPositionSync != mNeedsPositionSync) { 1460c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // update needed? 1461c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 1462c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 14634a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14644a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14654a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi 14664a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi /** pre-condition rcd != null */ 14674a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi private void onUpdateDisplayArtworkSize(IRemoteControlDisplay rcd, int w, int h) { 14684a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi synchronized(mCacheLock) { 14694a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 14704a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi while (displayIterator.hasNext()) { 14714a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 14724a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) && 14734a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) { 14744a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedWidth = w; 14754a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi di.mArtworkExpectedHeight = h; 14764a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi if (!sendArtworkToDisplay(di)) { 14774a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi displayIterator.remove(); 14784a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14794a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi break; 14804a5700556191c835116ec2a6997a4f16f464ac9dJean-Michel Trivi } 14814426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14824426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14834426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 14844426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 1485c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi /** pre-condition rcd != null */ 1486c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi private void onDisplayWantsSync(IRemoteControlDisplay rcd, boolean wantsSync) { 1487c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi synchronized(mCacheLock) { 1488c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean oldNeedsPositionSync = mNeedsPositionSync; 1489c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi boolean newNeedsPositionSync = false; 1490c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator(); 1491c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // go through the list of RCDs and for each entry, check both whether this is the RCD 1492c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // that gets upated, and whether the list has one entry that wants position sync 1493c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi while (displayIterator.hasNext()) { 1494c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next(); 1495c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) { 1496c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi di.mWantsPositionSync = wantsSync; 1497c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1498c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (di.mWantsPositionSync) { 1499c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi newNeedsPositionSync = true; 1500c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1501c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1502c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi mNeedsPositionSync = newNeedsPositionSync; 1503c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi if (oldNeedsPositionSync != mNeedsPositionSync) { 1504c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi // update needed? 1505c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi initiateCheckForDrift_syncCacheLock(); 1506c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1507c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1508c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi } 1509c3c4babf8424f65b3d3d2700f60fae6e94e9cd00Jean-Michel Trivi 15103261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi private void onSeekTo(int generationId, long timeMs) { 15113261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi synchronized (mCacheLock) { 15123261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi if ((mCurrentClientGenId == generationId) && (mPositionUpdateListener != null)) { 15133261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi mPositionUpdateListener.onPlaybackPositionUpdate(timeMs); 15143261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 15153261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 15163261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi } 15173261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi 15183114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi //=========================================================== 15193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // Internal utilities 15203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 15214426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi /** 15224426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * Scale a bitmap to fit the smallest dimension by uniformly scaling the incoming bitmap. 15234426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * If the bitmap fits, then do nothing and return the original. 15244426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * 15254426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param bitmap 15264426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param maxWidth 15274426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @param maxHeight 15284426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi * @return 15294426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi */ 15304426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 15314426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi private Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) { 15326e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi if (bitmap != null) { 15336e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi final int width = bitmap.getWidth(); 15346e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi final int height = bitmap.getHeight(); 15356e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi if (width > maxWidth || height > maxHeight) { 15366e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi float scale = Math.min((float) maxWidth / width, (float) maxHeight / height); 15376e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi int newWidth = Math.round(scale * width); 15386e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi int newHeight = Math.round(scale * height); 153905c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich Bitmap.Config newConfig = bitmap.getConfig(); 154005c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich if (newConfig == null) { 154105c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich newConfig = Bitmap.Config.ARGB_8888; 154205c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich } 154305c66cc5cc6357be19fdef0fc131731368c38646Jack Palevich Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, newConfig); 15446e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi Canvas canvas = new Canvas(outBitmap); 15456e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi Paint paint = new Paint(); 15466e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi paint.setAntiAlias(true); 15476e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi paint.setFilterBitmap(true); 15486e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi canvas.drawBitmap(bitmap, null, 15496e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint); 15506e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi bitmap = outBitmap; 15516e679d5a53091b348a2cdc0c76f4e8fa4ac52d4bJean-Michel Trivi } 15524426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 15534426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi return bitmap; 15545ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 15554426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi 15565ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi /** 15575ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * Fast routine to go through an array of allowed keys and return whether the key is part 15585ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * of that array 15595ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @param key the key value 15605ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @param validKeys the array of valid keys for a given type 15615ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi * @return true if the key is part of the array, false otherwise 15625ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi */ 15635ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi private static boolean validTypeForKey(int key, int[] validKeys) { 15645ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi try { 15655ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi for (int i = 0 ; ; i++) { 15665ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi if (key == validKeys[i]) { 15675ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi return true; 15685ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 15695ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 15705ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } catch (ArrayIndexOutOfBoundsException e) { 15715ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi return false; 15725ad4b9fb96089e460902ffac9f3649366afd3750Jean-Michel Trivi } 15734426e42ac6107bf6b09f7c4cdad39eb161d8b9caJean-Michel Trivi } 1574521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 1575521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1576521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Returns whether, for the given playback state, the playback position is expected to 1577521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * be changing. 1578521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @param playstate the playback state to evaluate 1579521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @return true during any form of playback, false if it's not playing anything while in this 1580521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * playback state 1581521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1582521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private static boolean playbackPositionShouldMove(int playstate) { 1583521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi switch(playstate) { 1584521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_STOPPED: 1585521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_PAUSED: 1586521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_BUFFERING: 1587521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_ERROR: 1588521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_SKIPPING_FORWARDS: 1589521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_SKIPPING_BACKWARDS: 1590521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return false; 1591521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_PLAYING: 1592521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_FAST_FORWARDING: 1593521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi case PLAYSTATE_REWINDING: 1594521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi default: 1595521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return true; 1596521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1597521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1598521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi 1599521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1600521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Period for playback position drift checks, 15s when playing at 1x or slower. 1601521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1602521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_REFRESH_PERIOD_PLAYING_MS = 15000; 1603521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1604521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Minimum period for playback position drift checks, never more often when every 2s, when 1605521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * fast forwarding or rewinding. 1606521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1607521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_REFRESH_PERIOD_MIN_MS = 2000; 1608521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1609521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * The value above which the difference between client-reported playback position and 1610521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * estimated position is considered a drift. 1611521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1612521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private final static long POSITION_DRIFT_MAX_MS = 500; 1613521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi /** 1614521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * Compute the period at which the estimated playback position should be compared against the 1615521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * actual playback position. Is a funciton of playback speed. 1616521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @param speed 1.0f is normal playback speed 1617521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi * @return the period in ms 1618521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi */ 1619521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi private static long getCheckPeriodFromSpeed(float speed) { 1620521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi if (Math.abs(speed) <= 1.0f) { 1621521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return POSITION_REFRESH_PERIOD_PLAYING_MS; 1622521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } else { 1623521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi return Math.max((long)(POSITION_REFRESH_PERIOD_PLAYING_MS / Math.abs(speed)), 1624521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi POSITION_REFRESH_PERIOD_MIN_MS); 1625521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1626521e68e76cfdcf297d0de056032dc142d4939fa0Jean-Michel Trivi } 1627178889eff7fa3361a5cb08d6d43846a1baf5216bJean-Michel Trivi} 1628