Skip to content

Commit 1a59c7e

Browse files
Jim MillerAndroid (Google) Code Review
authored andcommitted
Merge "Fix 5358124: Better transport control visibility management in lock screen" into ics-mr0
2 parents ed37b1b + 4e6d358 commit 1a59c7e

File tree

3 files changed

+123
-19
lines changed

3 files changed

+123
-19
lines changed

core/java/com/android/internal/widget/LockScreenWidgetCallback.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public interface LockScreenWidgetCallback {
2929
// Sends a message to lock screen requesting the view to be hidden.
3030
public void requestHide(View self);
3131

32+
// Whether or not this view is currently visible on LockScreen
33+
public boolean isVisible(View self);
34+
3235
// Sends a message to lock screen that user has interacted with widget. This should be used
3336
// exclusively in response to user activity, i.e. user hits a button in the view.
3437
public void userActivity(View self);

core/java/com/android/internal/widget/TransportControlView.java

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import android.os.Bundle;
3535
import android.os.Handler;
3636
import android.os.Message;
37+
import android.os.Parcel;
38+
import android.os.Parcelable;
3739
import android.os.RemoteException;
3840
import android.os.SystemClock;
3941
import android.text.Spannable;
@@ -61,7 +63,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
6163
private static final int MSG_SET_GENERATION_ID = 104;
6264
private static final int MAXDIM = 512;
6365
private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
64-
protected static final boolean DEBUG = true;
66+
protected static final boolean DEBUG = false;
6567
protected static final String TAG = "TransportControlView";
6668

6769
private ImageView mAlbumArt;
@@ -74,7 +76,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
7476
private boolean mAttached;
7577
private PendingIntent mClientIntent;
7678
private int mTransportControlFlags;
77-
private int mPlayState;
79+
private int mCurrentPlayState;
7880
private AudioManager mAudioManager;
7981
private LockScreenWidgetCallback mWidgetCallbacks;
8082
private IRemoteControlDisplayWeak mIRCD;
@@ -84,6 +86,11 @@ public class TransportControlView extends FrameLayout implements OnClickListener
8486
*/
8587
private Bundle mPopulateMetadataWhenAttached = null;
8688

89+
/**
90+
* Whether to clear the interface next time it is shown (i.e. the generation id changed)
91+
*/
92+
private boolean mClearOnNextShow;
93+
8794
// This handler is required to ensure messages from IRCD are handled in sequence and on
8895
// the UI thread.
8996
private Handler mHandler = new Handler() {
@@ -113,15 +120,10 @@ public void handleMessage(Message msg) {
113120
break;
114121

115122
case MSG_SET_GENERATION_ID:
116-
if (mWidgetCallbacks != null) {
117-
boolean clearing = msg.arg2 != 0;
118-
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + clearing);
119-
if (!clearing) {
120-
mWidgetCallbacks.requestShow(TransportControlView.this);
121-
} else {
122-
mWidgetCallbacks.requestHide(TransportControlView.this);
123-
}
123+
if (msg.arg2 != 0) {
124+
mClearOnNextShow = true; // TODO: handle this
124125
}
126+
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
125127
mClientGeneration = msg.arg1;
126128
mClientIntent = (PendingIntent) msg.obj;
127129
break;
@@ -195,6 +197,7 @@ public TransportControlView(Context context, AttributeSet attrs) {
195197
super(context, attrs);
196198
Log.v(TAG, "Create TCV " + this);
197199
mAudioManager = new AudioManager(mContext);
200+
mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
198201
mIRCD = new IRemoteControlDisplayWeak(mHandler);
199202
}
200203

@@ -319,7 +322,7 @@ private void populateMetadata() {
319322
| RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
320323
| RemoteControlClient.FLAG_KEY_MEDIA_STOP);
321324

322-
updatePlayPauseState(mPlayState);
325+
updatePlayPauseState(mCurrentPlayState);
323326
}
324327

325328
private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
@@ -332,12 +335,13 @@ private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
332335

333336
private void updatePlayPauseState(int state) {
334337
if (DEBUG) Log.v(TAG,
335-
"updatePlayPauseState(), old=" + mPlayState + ", state=" + state);
336-
if (state == mPlayState) {
338+
"updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
339+
if (state == mCurrentPlayState) {
337340
return;
338341
}
339342
final int imageResId;
340343
final int imageDescId;
344+
final boolean showIfHidden;
341345
switch (state) {
342346
case RemoteControlClient.PLAYSTATE_ERROR:
343347
imageResId = com.android.internal.R.drawable.stat_sys_warning;
@@ -349,22 +353,81 @@ private void updatePlayPauseState(int state) {
349353
case RemoteControlClient.PLAYSTATE_PLAYING:
350354
imageResId = com.android.internal.R.drawable.ic_media_pause;
351355
imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
356+
showIfHidden = true;
352357
break;
353358

354359
case RemoteControlClient.PLAYSTATE_BUFFERING:
355360
imageResId = com.android.internal.R.drawable.ic_media_stop;
356361
imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
362+
showIfHidden = true;
357363
break;
358364

359365
case RemoteControlClient.PLAYSTATE_PAUSED:
360366
default:
361367
imageResId = com.android.internal.R.drawable.ic_media_play;
362368
imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
369+
showIfHidden = false;
363370
break;
364371
}
365372
mBtnPlay.setImageResource(imageResId);
366373
mBtnPlay.setContentDescription(getResources().getString(imageDescId));
367-
mPlayState = state;
374+
if (showIfHidden && mWidgetCallbacks != null && !mWidgetCallbacks.isVisible(this)) {
375+
mWidgetCallbacks.requestShow(this);
376+
}
377+
mCurrentPlayState = state;
378+
}
379+
380+
static class SavedState extends BaseSavedState {
381+
boolean wasShowing;
382+
383+
SavedState(Parcelable superState) {
384+
super(superState);
385+
}
386+
387+
private SavedState(Parcel in) {
388+
super(in);
389+
this.wasShowing = in.readInt() != 0;
390+
}
391+
392+
@Override
393+
public void writeToParcel(Parcel out, int flags) {
394+
super.writeToParcel(out, flags);
395+
out.writeInt(this.wasShowing ? 1 : 0);
396+
}
397+
398+
public static final Parcelable.Creator<SavedState> CREATOR
399+
= new Parcelable.Creator<SavedState>() {
400+
public SavedState createFromParcel(Parcel in) {
401+
return new SavedState(in);
402+
}
403+
404+
public SavedState[] newArray(int size) {
405+
return new SavedState[size];
406+
}
407+
};
408+
}
409+
410+
@Override
411+
public Parcelable onSaveInstanceState() {
412+
if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
413+
Parcelable superState = super.onSaveInstanceState();
414+
SavedState ss = new SavedState(superState);
415+
ss.wasShowing = mWidgetCallbacks.isVisible(this);
416+
return ss;
417+
}
418+
419+
@Override
420+
public void onRestoreInstanceState(Parcelable state) {
421+
if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
422+
if (!(state instanceof SavedState)) {
423+
super.onRestoreInstanceState(state);
424+
return;
425+
}
426+
SavedState ss = (SavedState) state;
427+
super.onRestoreInstanceState(ss.getSuperState());
428+
if (ss.wasShowing) {
429+
mWidgetCallbacks.requestShow(this);
430+
}
368431
}
369432

370433
public void onClick(View v) {

policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import android.os.Handler;
5050
import android.os.Message;
5151
import android.os.IBinder;
52+
import android.os.Parcelable;
5253
import android.os.RemoteException;
5354
import android.os.SystemClock;
5455
import android.os.SystemProperties;
@@ -221,6 +222,7 @@ enum UnlockMode {
221222
private Runnable mRecreateRunnable = new Runnable() {
222223
public void run() {
223224
updateScreen(mMode, true);
225+
restoreWidgetState();
224226
}
225227
};
226228

@@ -244,8 +246,20 @@ public void requestHide(View view) {
244246
// TODO: examine all widgets to derive clock status
245247
mUpdateMonitor.reportClockVisible(true);
246248
}
249+
250+
public boolean isVisible(View self) {
251+
// TODO: this should be up to the lockscreen to determine if the view
252+
// is currently showing. The idea is it can be used for the widget to
253+
// avoid doing work if it's not visible. For now just returns the view's
254+
// actual visibility.
255+
return self.getVisibility() == View.VISIBLE;
256+
}
247257
};
248258

259+
private TransportControlView mTransportControlView;
260+
261+
private Parcelable mSavedState;
262+
249263
/**
250264
* @return Whether we are stuck on the lock screen because the sim is
251265
* missing.
@@ -365,6 +379,7 @@ public void pokeWakelock(int millis) {
365379

366380
public void keyguardDone(boolean authenticated) {
367381
getCallback().keyguardDone(authenticated);
382+
mSavedState = null; // clear state so we re-establish when locked again
368383
}
369384

370385
public void keyguardDoneDrawing() {
@@ -528,6 +543,8 @@ public void onScreenTurnedOff() {
528543
((KeyguardScreen) mUnlockScreen).onPause();
529544
}
530545

546+
saveWidgetState();
547+
531548
// When screen is turned off, need to unbind from FaceLock service if using FaceLock
532549
stopAndUnbindFromFaceLock();
533550
}
@@ -558,8 +575,28 @@ public void onScreenTurnedOn() {
558575
mScreenOn = true;
559576
runFaceLock = mWindowFocused;
560577
}
578+
561579
show();
562-
if(runFaceLock) activateFaceLockIfAble();
580+
581+
restoreWidgetState();
582+
583+
if (runFaceLock) activateFaceLockIfAble();
584+
}
585+
586+
private void saveWidgetState() {
587+
if (mTransportControlView != null) {
588+
if (DEBUG) Log.v(TAG, "Saving widget state");
589+
mSavedState = mTransportControlView.onSaveInstanceState();
590+
}
591+
}
592+
593+
private void restoreWidgetState() {
594+
if (mTransportControlView != null) {
595+
if (DEBUG) Log.v(TAG, "Restoring widget state");
596+
if (mSavedState != null) {
597+
mTransportControlView.onRestoreInstanceState(mSavedState);
598+
}
599+
}
563600
}
564601

565602
/** Unbind from facelock if something covers this window (such as an alarm)
@@ -643,6 +680,7 @@ protected void onConfigurationChanged(Configuration newConfig) {
643680
mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
644681
mConfiguration = newConfig;
645682
if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
683+
saveWidgetState();
646684
removeCallbacks(mRecreateRunnable);
647685
post(mRecreateRunnable);
648686
}
@@ -895,13 +933,13 @@ View createUnlockScreenFor(UnlockMode unlockMode) {
895933
}
896934

897935
private void initializeTransportControlView(View view) {
898-
TransportControlView tcv = (TransportControlView) view.findViewById(R.id.transport);
899-
if (tcv == null) {
936+
mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
937+
if (mTransportControlView == null) {
900938
if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
901939
} else {
902940
mUpdateMonitor.reportClockVisible(true);
903-
tcv.setVisibility(View.GONE); // hide until it requests being shown.
904-
tcv.setCallback(mWidgetCallback);
941+
mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
942+
mTransportControlView.setCallback(mWidgetCallback);
905943
}
906944
}
907945

0 commit comments

Comments
 (0)