16b05d58018c2806459c121e507c005639b74aee9Jim Miller/* 26b05d58018c2806459c121e507c005639b74aee9Jim Miller * Copyright (C) 2011 The Android Open Source Project 36b05d58018c2806459c121e507c005639b74aee9Jim Miller * 46b05d58018c2806459c121e507c005639b74aee9Jim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 56b05d58018c2806459c121e507c005639b74aee9Jim Miller * you may not use this file except in compliance with the License. 66b05d58018c2806459c121e507c005639b74aee9Jim Miller * You may obtain a copy of the License at 76b05d58018c2806459c121e507c005639b74aee9Jim Miller * 86b05d58018c2806459c121e507c005639b74aee9Jim Miller * http://www.apache.org/licenses/LICENSE-2.0 96b05d58018c2806459c121e507c005639b74aee9Jim Miller * 106b05d58018c2806459c121e507c005639b74aee9Jim Miller * Unless required by applicable law or agreed to in writing, software 116b05d58018c2806459c121e507c005639b74aee9Jim Miller * distributed under the License is distributed on an "AS IS" BASIS, 126b05d58018c2806459c121e507c005639b74aee9Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b05d58018c2806459c121e507c005639b74aee9Jim Miller * See the License for the specific language governing permissions and 146b05d58018c2806459c121e507c005639b74aee9Jim Miller * limitations under the License. 156b05d58018c2806459c121e507c005639b74aee9Jim Miller */ 166b05d58018c2806459c121e507c005639b74aee9Jim Miller 176b05d58018c2806459c121e507c005639b74aee9Jim Millerpackage com.android.internal.widget; 186b05d58018c2806459c121e507c005639b74aee9Jim Miller 191c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport java.lang.ref.WeakReference; 201c18828d20807342d37000746b18a3c1696f3b2eJim Miller 211c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport com.android.internal.widget.LockScreenWidgetCallback; 221c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport com.android.internal.widget.LockScreenWidgetInterface; 236b05d58018c2806459c121e507c005639b74aee9Jim Miller 24f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.app.PendingIntent; 25f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.app.PendingIntent.CanceledException; 266b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.content.Context; 271c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.content.Intent; 281c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.graphics.Bitmap; 296b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.media.AudioManager; 301c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.media.MediaMetadataRetriever; 311c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.media.RemoteControlClient; 321c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.media.IRemoteControlDisplay; 331c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.os.Bundle; 346b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.os.Handler; 356b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.os.Message; 364e6d35829ebf98ea37f77ea434550d51950c1119Jim Millerimport android.os.Parcel; 374e6d35829ebf98ea37f77ea434550d51950c1119Jim Millerimport android.os.Parcelable; 381c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.os.RemoteException; 3968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Triviimport android.os.SystemClock; 401c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.text.Spannable; 411c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.text.TextUtils; 421c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.text.style.ForegroundColorSpan; 436b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.util.AttributeSet; 441c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.util.Log; 451c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.view.KeyEvent; 466b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.view.View; 476b05d58018c2806459c121e507c005639b74aee9Jim Millerimport android.view.View.OnClickListener; 481c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.widget.FrameLayout; 491c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.widget.ImageView; 501c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport android.widget.TextView; 516b05d58018c2806459c121e507c005639b74aee9Jim Miller 526b05d58018c2806459c121e507c005639b74aee9Jim Miller 531c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport com.android.internal.R; 541c18828d20807342d37000746b18a3c1696f3b2eJim Miller 551c18828d20807342d37000746b18a3c1696f3b2eJim Millerpublic class TransportControlView extends FrameLayout implements OnClickListener, 561c18828d20807342d37000746b18a3c1696f3b2eJim Miller LockScreenWidgetInterface { 571c18828d20807342d37000746b18a3c1696f3b2eJim Miller 581c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MSG_UPDATE_STATE = 100; 591c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MSG_SET_METADATA = 101; 601c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MSG_SET_TRANSPORT_CONTROLS = 102; 611c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MSG_SET_ARTWORK = 103; 621c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MSG_SET_GENERATION_ID = 104; 631c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static final int MAXDIM = 512; 6468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s 654e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller protected static final boolean DEBUG = false; 661c18828d20807342d37000746b18a3c1696f3b2eJim Miller protected static final String TAG = "TransportControlView"; 671c18828d20807342d37000746b18a3c1696f3b2eJim Miller 681c18828d20807342d37000746b18a3c1696f3b2eJim Miller private ImageView mAlbumArt; 691c18828d20807342d37000746b18a3c1696f3b2eJim Miller private TextView mTrackTitle; 701c18828d20807342d37000746b18a3c1696f3b2eJim Miller private ImageView mBtnPrev; 711c18828d20807342d37000746b18a3c1696f3b2eJim Miller private ImageView mBtnPlay; 721c18828d20807342d37000746b18a3c1696f3b2eJim Miller private ImageView mBtnNext; 731c18828d20807342d37000746b18a3c1696f3b2eJim Miller private int mClientGeneration; 741c18828d20807342d37000746b18a3c1696f3b2eJim Miller private Metadata mMetadata = new Metadata(); 751c18828d20807342d37000746b18a3c1696f3b2eJim Miller private boolean mAttached; 76f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi private PendingIntent mClientIntent; 771c18828d20807342d37000746b18a3c1696f3b2eJim Miller private int mTransportControlFlags; 784e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller private int mCurrentPlayState; 791c18828d20807342d37000746b18a3c1696f3b2eJim Miller private AudioManager mAudioManager; 801c18828d20807342d37000746b18a3c1696f3b2eJim Miller private LockScreenWidgetCallback mWidgetCallbacks; 811c18828d20807342d37000746b18a3c1696f3b2eJim Miller private IRemoteControlDisplayWeak mIRCD; 821c18828d20807342d37000746b18a3c1696f3b2eJim Miller 831c18828d20807342d37000746b18a3c1696f3b2eJim Miller /** 841c18828d20807342d37000746b18a3c1696f3b2eJim Miller * The metadata which should be populated into the view once we've been attached 851c18828d20807342d37000746b18a3c1696f3b2eJim Miller */ 861c18828d20807342d37000746b18a3c1696f3b2eJim Miller private Bundle mPopulateMetadataWhenAttached = null; 871c18828d20807342d37000746b18a3c1696f3b2eJim Miller 881c18828d20807342d37000746b18a3c1696f3b2eJim Miller // This handler is required to ensure messages from IRCD are handled in sequence and on 891c18828d20807342d37000746b18a3c1696f3b2eJim Miller // the UI thread. 906b05d58018c2806459c121e507c005639b74aee9Jim Miller private Handler mHandler = new Handler() { 911c18828d20807342d37000746b18a3c1696f3b2eJim Miller @Override 926b05d58018c2806459c121e507c005639b74aee9Jim Miller public void handleMessage(Message msg) { 931c18828d20807342d37000746b18a3c1696f3b2eJim Miller switch (msg.what) { 941c18828d20807342d37000746b18a3c1696f3b2eJim Miller case MSG_UPDATE_STATE: 951c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mClientGeneration == msg.arg1) updatePlayPauseState(msg.arg2); 961c18828d20807342d37000746b18a3c1696f3b2eJim Miller break; 971c18828d20807342d37000746b18a3c1696f3b2eJim Miller 981c18828d20807342d37000746b18a3c1696f3b2eJim Miller case MSG_SET_METADATA: 991c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mClientGeneration == msg.arg1) updateMetadata((Bundle) msg.obj); 1001c18828d20807342d37000746b18a3c1696f3b2eJim Miller break; 1011c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1021c18828d20807342d37000746b18a3c1696f3b2eJim Miller case MSG_SET_TRANSPORT_CONTROLS: 1031c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mClientGeneration == msg.arg1) updateTransportControls(msg.arg2); 1041c18828d20807342d37000746b18a3c1696f3b2eJim Miller break; 1051c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1061c18828d20807342d37000746b18a3c1696f3b2eJim Miller case MSG_SET_ARTWORK: 1071c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mClientGeneration == msg.arg1) { 10801d96bd2afdcff866e0e1010eb7c88e101d0f6faJean-Michel Trivi if (mMetadata.bitmap != null) { 10901d96bd2afdcff866e0e1010eb7c88e101d0f6faJean-Michel Trivi mMetadata.bitmap.recycle(); 11001d96bd2afdcff866e0e1010eb7c88e101d0f6faJean-Michel Trivi } 1111c18828d20807342d37000746b18a3c1696f3b2eJim Miller mMetadata.bitmap = (Bitmap) msg.obj; 1121c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAlbumArt.setImageBitmap(mMetadata.bitmap); 1131c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1141c18828d20807342d37000746b18a3c1696f3b2eJim Miller break; 1151c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1161c18828d20807342d37000746b18a3c1696f3b2eJim Miller case MSG_SET_GENERATION_ID: 1174e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (msg.arg2 != 0) { 118a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller // This means nobody is currently registered. Hide the view. 119a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller if (mWidgetCallbacks != null) { 120a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller mWidgetCallbacks.requestHide(TransportControlView.this); 121a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller } 1221c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1234e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2); 1241c18828d20807342d37000746b18a3c1696f3b2eJim Miller mClientGeneration = msg.arg1; 125f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mClientIntent = (PendingIntent) msg.obj; 1261c18828d20807342d37000746b18a3c1696f3b2eJim Miller break; 1271c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1286b05d58018c2806459c121e507c005639b74aee9Jim Miller } 1296b05d58018c2806459c121e507c005639b74aee9Jim Miller } 1306b05d58018c2806459c121e507c005639b74aee9Jim Miller }; 1316b05d58018c2806459c121e507c005639b74aee9Jim Miller 1321c18828d20807342d37000746b18a3c1696f3b2eJim Miller /** 1331c18828d20807342d37000746b18a3c1696f3b2eJim Miller * This class is required to have weak linkage to the current TransportControlView 1341c18828d20807342d37000746b18a3c1696f3b2eJim Miller * because the remote process can hold a strong reference to this binder object and 1351c18828d20807342d37000746b18a3c1696f3b2eJim Miller * we can't predict when it will be GC'd in the remote process. Without this code, it 1361c18828d20807342d37000746b18a3c1696f3b2eJim Miller * would allow a heavyweight object to be held on this side of the binder when there's 1371c18828d20807342d37000746b18a3c1696f3b2eJim Miller * no requirement to run a GC on the other side. 1381c18828d20807342d37000746b18a3c1696f3b2eJim Miller */ 1391c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static class IRemoteControlDisplayWeak extends IRemoteControlDisplay.Stub { 1401c18828d20807342d37000746b18a3c1696f3b2eJim Miller private WeakReference<Handler> mLocalHandler; 1411c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1421c18828d20807342d37000746b18a3c1696f3b2eJim Miller IRemoteControlDisplayWeak(Handler handler) { 1431c18828d20807342d37000746b18a3c1696f3b2eJim Miller mLocalHandler = new WeakReference<Handler>(handler); 1441c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1451c18828d20807342d37000746b18a3c1696f3b2eJim Miller 146bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi public void setPlaybackState(int generationId, int state, long stateChangeTimeMs, 147bc43b4c2f24fd03c0d0546895c97918c1736d9fbJean-Michel Trivi long currentPosMs, float speed) { 1481c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1491c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1501c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget(); 1516b05d58018c2806459c121e507c005639b74aee9Jim Miller } 1521c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1536b05d58018c2806459c121e507c005639b74aee9Jim Miller 1541c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void setMetadata(int generationId, Bundle metadata) { 1551c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1561c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1571c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget(); 1581c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1591c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1601c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1613261b537c5fdec824575a1f6ad6d8942715e82e2Jean-Michel Trivi public void setTransportControlInfo(int generationId, int flags, int posCapabilities) { 1621c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1631c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1641c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, generationId, flags) 1651c18828d20807342d37000746b18a3c1696f3b2eJim Miller .sendToTarget(); 1661c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1671c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1681c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1691c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void setArtwork(int generationId, Bitmap bitmap) { 1701c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1711c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1721c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget(); 1731c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1741c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1751c18828d20807342d37000746b18a3c1696f3b2eJim Miller 1761c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) { 1771c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1781c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1791c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget(); 1801c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget(); 1811c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1821c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1831c18828d20807342d37000746b18a3c1696f3b2eJim Miller 184f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent, 1851c18828d20807342d37000746b18a3c1696f3b2eJim Miller boolean clearing) throws RemoteException { 1861c18828d20807342d37000746b18a3c1696f3b2eJim Miller Handler handler = mLocalHandler.get(); 1871c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (handler != null) { 1881c18828d20807342d37000746b18a3c1696f3b2eJim Miller handler.obtainMessage(MSG_SET_GENERATION_ID, 189f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi clientGeneration, (clearing ? 1 : 0), mediaIntent).sendToTarget(); 1901c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1911c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 1921c18828d20807342d37000746b18a3c1696f3b2eJim Miller }; 1936b05d58018c2806459c121e507c005639b74aee9Jim Miller 1946b05d58018c2806459c121e507c005639b74aee9Jim Miller public TransportControlView(Context context, AttributeSet attrs) { 1956b05d58018c2806459c121e507c005639b74aee9Jim Miller super(context, attrs); 1967ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn if (DEBUG) Log.v(TAG, "Create TCV " + this); 1971c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAudioManager = new AudioManager(mContext); 1984e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback 1991c18828d20807342d37000746b18a3c1696f3b2eJim Miller mIRCD = new IRemoteControlDisplayWeak(mHandler); 2006b05d58018c2806459c121e507c005639b74aee9Jim Miller } 2016b05d58018c2806459c121e507c005639b74aee9Jim Miller 2021c18828d20807342d37000746b18a3c1696f3b2eJim Miller private void updateTransportControls(int transportControlFlags) { 2031c18828d20807342d37000746b18a3c1696f3b2eJim Miller mTransportControlFlags = transportControlFlags; 2046b05d58018c2806459c121e507c005639b74aee9Jim Miller } 2056b05d58018c2806459c121e507c005639b74aee9Jim Miller 2061c18828d20807342d37000746b18a3c1696f3b2eJim Miller @Override 2071c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void onFinishInflate() { 2081c18828d20807342d37000746b18a3c1696f3b2eJim Miller super.onFinishInflate(); 2091c18828d20807342d37000746b18a3c1696f3b2eJim Miller mTrackTitle = (TextView) findViewById(R.id.title); 2101c18828d20807342d37000746b18a3c1696f3b2eJim Miller mTrackTitle.setSelected(true); // enable marquee 2111c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAlbumArt = (ImageView) findViewById(R.id.albumart); 2121c18828d20807342d37000746b18a3c1696f3b2eJim Miller mBtnPrev = (ImageView) findViewById(R.id.btn_prev); 2131c18828d20807342d37000746b18a3c1696f3b2eJim Miller mBtnPlay = (ImageView) findViewById(R.id.btn_play); 2141c18828d20807342d37000746b18a3c1696f3b2eJim Miller mBtnNext = (ImageView) findViewById(R.id.btn_next); 2151c18828d20807342d37000746b18a3c1696f3b2eJim Miller final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext }; 2161c18828d20807342d37000746b18a3c1696f3b2eJim Miller for (View view : buttons) { 2171c18828d20807342d37000746b18a3c1696f3b2eJim Miller view.setOnClickListener(this); 2181c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2196b05d58018c2806459c121e507c005639b74aee9Jim Miller } 2206b05d58018c2806459c121e507c005639b74aee9Jim Miller 2216b05d58018c2806459c121e507c005639b74aee9Jim Miller @Override 2221c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void onAttachedToWindow() { 2231c18828d20807342d37000746b18a3c1696f3b2eJim Miller super.onAttachedToWindow(); 2241c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mPopulateMetadataWhenAttached != null) { 2251c18828d20807342d37000746b18a3c1696f3b2eJim Miller updateMetadata(mPopulateMetadataWhenAttached); 2261c18828d20807342d37000746b18a3c1696f3b2eJim Miller mPopulateMetadataWhenAttached = null; 2271c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2281c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (!mAttached) { 2291c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (DEBUG) Log.v(TAG, "Registering TCV " + this); 2301c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAudioManager.registerRemoteControlDisplay(mIRCD); 2311c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2321c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAttached = true; 2331c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2341c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2351c18828d20807342d37000746b18a3c1696f3b2eJim Miller @Override 2361c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void onDetachedFromWindow() { 2371c18828d20807342d37000746b18a3c1696f3b2eJim Miller super.onDetachedFromWindow(); 2381c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mAttached) { 2391c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (DEBUG) Log.v(TAG, "Unregistering TCV " + this); 2401c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAudioManager.unregisterRemoteControlDisplay(mIRCD); 2411c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2421c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAttached = false; 2431c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2441c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2451c18828d20807342d37000746b18a3c1696f3b2eJim Miller @Override 2461c18828d20807342d37000746b18a3c1696f3b2eJim Miller protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 2471c18828d20807342d37000746b18a3c1696f3b2eJim Miller super.onMeasure(widthMeasureSpec, heightMeasureSpec); 2481c18828d20807342d37000746b18a3c1696f3b2eJim Miller int dim = Math.min(MAXDIM, Math.max(getWidth(), getHeight())); 2491c18828d20807342d37000746b18a3c1696f3b2eJim Miller// Log.v(TAG, "setting max bitmap size: " + dim + "x" + dim); 2501c18828d20807342d37000746b18a3c1696f3b2eJim Miller// mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim); 2511c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2521c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2531c18828d20807342d37000746b18a3c1696f3b2eJim Miller class Metadata { 2541c18828d20807342d37000746b18a3c1696f3b2eJim Miller private String artist; 2551c18828d20807342d37000746b18a3c1696f3b2eJim Miller private String trackTitle; 2561c18828d20807342d37000746b18a3c1696f3b2eJim Miller private String albumTitle; 2571c18828d20807342d37000746b18a3c1696f3b2eJim Miller private Bitmap bitmap; 2581c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2591c18828d20807342d37000746b18a3c1696f3b2eJim Miller public String toString() { 2601c18828d20807342d37000746b18a3c1696f3b2eJim Miller return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + albumTitle + "]"; 2611c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2621c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2631c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2641c18828d20807342d37000746b18a3c1696f3b2eJim Miller private String getMdString(Bundle data, int id) { 2651c18828d20807342d37000746b18a3c1696f3b2eJim Miller return data.getString(Integer.toString(id)); 2661c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2671c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2681c18828d20807342d37000746b18a3c1696f3b2eJim Miller private void updateMetadata(Bundle data) { 2691c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mAttached) { 2701c18828d20807342d37000746b18a3c1696f3b2eJim Miller mMetadata.artist = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST); 2711c18828d20807342d37000746b18a3c1696f3b2eJim Miller mMetadata.trackTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_TITLE); 2721c18828d20807342d37000746b18a3c1696f3b2eJim Miller mMetadata.albumTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUM); 2731c18828d20807342d37000746b18a3c1696f3b2eJim Miller populateMetadata(); 2741c18828d20807342d37000746b18a3c1696f3b2eJim Miller } else { 2751c18828d20807342d37000746b18a3c1696f3b2eJim Miller mPopulateMetadataWhenAttached = data; 2761c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2771c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2781c18828d20807342d37000746b18a3c1696f3b2eJim Miller 2791c18828d20807342d37000746b18a3c1696f3b2eJim Miller /** 2801c18828d20807342d37000746b18a3c1696f3b2eJim Miller * Populates the given metadata into the view 2811c18828d20807342d37000746b18a3c1696f3b2eJim Miller */ 2821c18828d20807342d37000746b18a3c1696f3b2eJim Miller private void populateMetadata() { 2831c18828d20807342d37000746b18a3c1696f3b2eJim Miller StringBuilder sb = new StringBuilder(); 2841c18828d20807342d37000746b18a3c1696f3b2eJim Miller int trackTitleLength = 0; 2851c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (!TextUtils.isEmpty(mMetadata.trackTitle)) { 2861c18828d20807342d37000746b18a3c1696f3b2eJim Miller sb.append(mMetadata.trackTitle); 2871c18828d20807342d37000746b18a3c1696f3b2eJim Miller trackTitleLength = mMetadata.trackTitle.length(); 2881c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2891c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (!TextUtils.isEmpty(mMetadata.artist)) { 2901c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (sb.length() != 0) { 2911c18828d20807342d37000746b18a3c1696f3b2eJim Miller sb.append(" - "); 2921c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2931c18828d20807342d37000746b18a3c1696f3b2eJim Miller sb.append(mMetadata.artist); 2941c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 2951c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (!TextUtils.isEmpty(mMetadata.albumTitle)) { 2961c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (sb.length() != 0) { 2971c18828d20807342d37000746b18a3c1696f3b2eJim Miller sb.append(" - "); 2986b05d58018c2806459c121e507c005639b74aee9Jim Miller } 2991c18828d20807342d37000746b18a3c1696f3b2eJim Miller sb.append(mMetadata.albumTitle); 3001c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 3011c18828d20807342d37000746b18a3c1696f3b2eJim Miller mTrackTitle.setText(sb.toString(), TextView.BufferType.SPANNABLE); 3021c18828d20807342d37000746b18a3c1696f3b2eJim Miller Spannable str = (Spannable) mTrackTitle.getText(); 3031c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (trackTitleLength != 0) { 3041c18828d20807342d37000746b18a3c1696f3b2eJim Miller str.setSpan(new ForegroundColorSpan(0xffffffff), 0, trackTitleLength, 3051c18828d20807342d37000746b18a3c1696f3b2eJim Miller Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 3061c18828d20807342d37000746b18a3c1696f3b2eJim Miller trackTitleLength++; 3071c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 3081c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (sb.length() > trackTitleLength) { 3091c18828d20807342d37000746b18a3c1696f3b2eJim Miller str.setSpan(new ForegroundColorSpan(0x7fffffff), trackTitleLength, sb.length(), 3101c18828d20807342d37000746b18a3c1696f3b2eJim Miller Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 3116b05d58018c2806459c121e507c005639b74aee9Jim Miller } 3121c18828d20807342d37000746b18a3c1696f3b2eJim Miller 3131c18828d20807342d37000746b18a3c1696f3b2eJim Miller mAlbumArt.setImageBitmap(mMetadata.bitmap); 3141c18828d20807342d37000746b18a3c1696f3b2eJim Miller final int flags = mTransportControlFlags; 3151c18828d20807342d37000746b18a3c1696f3b2eJim Miller setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS); 3161c18828d20807342d37000746b18a3c1696f3b2eJim Miller setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT); 3171f0eac9951c7167ee9f07251d1ef60805b96bffdJim Miller setVisibilityBasedOnFlag(mBtnPlay, flags, 3181c18828d20807342d37000746b18a3c1696f3b2eJim Miller RemoteControlClient.FLAG_KEY_MEDIA_PLAY 3191c18828d20807342d37000746b18a3c1696f3b2eJim Miller | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE 3201c18828d20807342d37000746b18a3c1696f3b2eJim Miller | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE 3211c18828d20807342d37000746b18a3c1696f3b2eJim Miller | RemoteControlClient.FLAG_KEY_MEDIA_STOP); 3221c18828d20807342d37000746b18a3c1696f3b2eJim Miller 3234e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller updatePlayPauseState(mCurrentPlayState); 3246b05d58018c2806459c121e507c005639b74aee9Jim Miller } 3256b05d58018c2806459c121e507c005639b74aee9Jim Miller 3261c18828d20807342d37000746b18a3c1696f3b2eJim Miller private static void setVisibilityBasedOnFlag(View view, int flags, int flag) { 3271c18828d20807342d37000746b18a3c1696f3b2eJim Miller if ((flags & flag) != 0) { 3281c18828d20807342d37000746b18a3c1696f3b2eJim Miller view.setVisibility(View.VISIBLE); 3291c18828d20807342d37000746b18a3c1696f3b2eJim Miller } else { 3301c18828d20807342d37000746b18a3c1696f3b2eJim Miller view.setVisibility(View.GONE); 3311c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 3321c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 3331c18828d20807342d37000746b18a3c1696f3b2eJim Miller 3341c18828d20807342d37000746b18a3c1696f3b2eJim Miller private void updatePlayPauseState(int state) { 3351c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (DEBUG) Log.v(TAG, 3364e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller "updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state); 3374e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (state == mCurrentPlayState) { 3381c18828d20807342d37000746b18a3c1696f3b2eJim Miller return; 3391c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 34067e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller final int imageResId; 34167e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller final int imageDescId; 34283e160d3b3ad839b0c2faf40f4477a2468098995Jim Miller boolean showIfHidden = false; 3431c18828d20807342d37000746b18a3c1696f3b2eJim Miller switch (state) { 344261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_ERROR: 345261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi imageResId = com.android.internal.R.drawable.stat_sys_warning; 346261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi // TODO use more specific image description string for warning, but here the "play" 347261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi // message is still valid because this button triggers a play command. 348261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi imageDescId = com.android.internal.R.string.lockscreen_transport_play_description; 349261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi break; 350261381cf9f52776f5f5fad8e6d2d31960c60c945Jean-Michel Trivi 3511c18828d20807342d37000746b18a3c1696f3b2eJim Miller case RemoteControlClient.PLAYSTATE_PLAYING: 35267e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageResId = com.android.internal.R.drawable.ic_media_pause; 35367e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description; 3544e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller showIfHidden = true; 3556b05d58018c2806459c121e507c005639b74aee9Jim Miller break; 3566b05d58018c2806459c121e507c005639b74aee9Jim Miller 3571c18828d20807342d37000746b18a3c1696f3b2eJim Miller case RemoteControlClient.PLAYSTATE_BUFFERING: 35867e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageResId = com.android.internal.R.drawable.ic_media_stop; 35967e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description; 3604e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller showIfHidden = true; 3616b05d58018c2806459c121e507c005639b74aee9Jim Miller break; 3626b05d58018c2806459c121e507c005639b74aee9Jim Miller 3631c18828d20807342d37000746b18a3c1696f3b2eJim Miller case RemoteControlClient.PLAYSTATE_PAUSED: 3641c18828d20807342d37000746b18a3c1696f3b2eJim Miller default: 36567e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageResId = com.android.internal.R.drawable.ic_media_play; 36667e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller imageDescId = com.android.internal.R.string.lockscreen_transport_play_description; 3674e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller showIfHidden = false; 3686b05d58018c2806459c121e507c005639b74aee9Jim Miller break; 3696b05d58018c2806459c121e507c005639b74aee9Jim Miller } 37067e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller mBtnPlay.setImageResource(imageResId); 37167e043db11b29f3c0c84529ae21a0fdd7ae11c6dJim Miller mBtnPlay.setContentDescription(getResources().getString(imageDescId)); 3724e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (showIfHidden && mWidgetCallbacks != null && !mWidgetCallbacks.isVisible(this)) { 3734e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller mWidgetCallbacks.requestShow(this); 3744e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 3754e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller mCurrentPlayState = state; 3764e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 3774e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 3784e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller static class SavedState extends BaseSavedState { 3794e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller boolean wasShowing; 3804e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 3814e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller SavedState(Parcelable superState) { 3824e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller super(superState); 3834e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 3844e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 3854e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller private SavedState(Parcel in) { 3864e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller super(in); 3874e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller this.wasShowing = in.readInt() != 0; 3884e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 3894e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 3904e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller @Override 3914e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public void writeToParcel(Parcel out, int flags) { 3924e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller super.writeToParcel(out, flags); 3934e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller out.writeInt(this.wasShowing ? 1 : 0); 3944e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 3954e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 3964e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public static final Parcelable.Creator<SavedState> CREATOR 3974e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller = new Parcelable.Creator<SavedState>() { 3984e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public SavedState createFromParcel(Parcel in) { 3994e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller return new SavedState(in); 4004e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4014e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 4024e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public SavedState[] newArray(int size) { 4034e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller return new SavedState[size]; 4044e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4054e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller }; 4064e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4074e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 4084e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller @Override 4094e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public Parcelable onSaveInstanceState() { 4104e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (DEBUG) Log.v(TAG, "onSaveInstanceState()"); 4114e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller Parcelable superState = super.onSaveInstanceState(); 4124e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller SavedState ss = new SavedState(superState); 413a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller ss.wasShowing = mWidgetCallbacks != null && mWidgetCallbacks.isVisible(this); 4144e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller return ss; 4154e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4164e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller 4174e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller @Override 4184e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller public void onRestoreInstanceState(Parcelable state) { 4194e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (DEBUG) Log.v(TAG, "onRestoreInstanceState()"); 4204e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller if (!(state instanceof SavedState)) { 4214e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller super.onRestoreInstanceState(state); 4224e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller return; 4234e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4244e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller SavedState ss = (SavedState) state; 4254e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller super.onRestoreInstanceState(ss.getSuperState()); 426a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller if (ss.wasShowing && mWidgetCallbacks != null) { 4274e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller mWidgetCallbacks.requestShow(this); 4284e6d35829ebf98ea37f77ea434550d51950c1119Jim Miller } 4291c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 4301c18828d20807342d37000746b18a3c1696f3b2eJim Miller 4311c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void onClick(View v) { 4321c18828d20807342d37000746b18a3c1696f3b2eJim Miller int keyCode = -1; 4331c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (v == mBtnPrev) { 4341c18828d20807342d37000746b18a3c1696f3b2eJim Miller keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS; 4351c18828d20807342d37000746b18a3c1696f3b2eJim Miller } else if (v == mBtnNext) { 4361c18828d20807342d37000746b18a3c1696f3b2eJim Miller keyCode = KeyEvent.KEYCODE_MEDIA_NEXT; 4371c18828d20807342d37000746b18a3c1696f3b2eJim Miller } else if (v == mBtnPlay) { 4381c18828d20807342d37000746b18a3c1696f3b2eJim Miller keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE; 4391c18828d20807342d37000746b18a3c1696f3b2eJim Miller 4401c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 4411c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (keyCode != -1) { 4421c18828d20807342d37000746b18a3c1696f3b2eJim Miller sendMediaButtonClick(keyCode); 4431c18828d20807342d37000746b18a3c1696f3b2eJim Miller if (mWidgetCallbacks != null) { 4441c18828d20807342d37000746b18a3c1696f3b2eJim Miller mWidgetCallbacks.userActivity(this); 4451c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 4466b05d58018c2806459c121e507c005639b74aee9Jim Miller } 4476b05d58018c2806459c121e507c005639b74aee9Jim Miller } 4486b05d58018c2806459c121e507c005639b74aee9Jim Miller 4491c18828d20807342d37000746b18a3c1696f3b2eJim Miller private void sendMediaButtonClick(int keyCode) { 450a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller if (mClientIntent == null) { 451a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller // Shouldn't be possible because this view should be hidden in this case. 452a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller Log.e(TAG, "sendMediaButtonClick(): No client is currently registered"); 453a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller return; 454a5ff5b482ab74b327983652439bea58c0499bae0Jim Miller } 455f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi // use the registered PendingIntent that will be processed by the registered 456f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi // media button event receiver, which is the component of mClientIntent 4571c18828d20807342d37000746b18a3c1696f3b2eJim Miller KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); 4581c18828d20807342d37000746b18a3c1696f3b2eJim Miller Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); 4591c18828d20807342d37000746b18a3c1696f3b2eJim Miller intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); 460f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi try { 461f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mClientIntent.send(getContext(), 0, intent); 462f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi } catch (CanceledException e) { 463f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi Log.e(TAG, "Error sending intent for media button down: "+e); 464f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi e.printStackTrace(); 465f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi } 4661c18828d20807342d37000746b18a3c1696f3b2eJim Miller 4671c18828d20807342d37000746b18a3c1696f3b2eJim Miller keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode); 4681c18828d20807342d37000746b18a3c1696f3b2eJim Miller intent = new Intent(Intent.ACTION_MEDIA_BUTTON); 4691c18828d20807342d37000746b18a3c1696f3b2eJim Miller intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); 470f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi try { 471f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi mClientIntent.send(getContext(), 0, intent); 472f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi } catch (CanceledException e) { 473f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi Log.e(TAG, "Error sending intent for media button up: "+e); 474f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi e.printStackTrace(); 475f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Trivi } 4761c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 4771c18828d20807342d37000746b18a3c1696f3b2eJim Miller 4781c18828d20807342d37000746b18a3c1696f3b2eJim Miller public void setCallback(LockScreenWidgetCallback callback) { 4791c18828d20807342d37000746b18a3c1696f3b2eJim Miller mWidgetCallbacks = callback; 4801c18828d20807342d37000746b18a3c1696f3b2eJim Miller } 4811c18828d20807342d37000746b18a3c1696f3b2eJim Miller 482054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey public boolean providesClock() { 483054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey return false; 484054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey } 485054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey 48668622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi private boolean wasPlayingRecently(int state, long stateChangeTimeMs) { 48768622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi switch (state) { 48868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_PLAYING: 48968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: 49068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_REWINDING: 49168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS: 49268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: 49368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_BUFFERING: 49468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // actively playing or about to play 49568622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi return true; 49668622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_NONE: 49768622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi return false; 49868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_STOPPED: 49968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_PAUSED: 50068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi case RemoteControlClient.PLAYSTATE_ERROR: 50168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi // we have stopped playing, check how long ago 50268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi if (DEBUG) { 50368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi if ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS) { 50468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi Log.v(TAG, "wasPlayingRecently: time < TIMEOUT was playing recently"); 50568622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } else { 50668622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi Log.v(TAG, "wasPlayingRecently: time > TIMEOUT"); 50768622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 50868622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 50968622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi return ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS); 51068622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi default: 51168622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi Log.e(TAG, "Unknown playback state " + state + " in wasPlayingRecently()"); 51268622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi return false; 51368622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 51468622396b62f9084781add1e12f4d513b633ab54Jean-Michel Trivi } 5156b05d58018c2806459c121e507c005639b74aee9Jim Miller} 516