Merge "Fix 5358124: Better transport control visibility management in lock screen" into ics-mr0

This commit is contained in:
Jim Miller
2011-10-14 10:19:13 -07:00
committed by Android (Google) Code Review
3 changed files with 123 additions and 19 deletions

View File

@@ -29,6 +29,9 @@ public interface LockScreenWidgetCallback {
// Sends a message to lock screen requesting the view to be hidden.
public void requestHide(View self);
// Whether or not this view is currently visible on LockScreen
public boolean isVisible(View self);
// Sends a message to lock screen that user has interacted with widget. This should be used
// exclusively in response to user activity, i.e. user hits a button in the view.
public void userActivity(View self);

View File

@@ -34,6 +34,8 @@ import android.media.IRemoteControlDisplay;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.Spannable;
@@ -61,7 +63,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
private static final int MSG_SET_GENERATION_ID = 104;
private static final int MAXDIM = 512;
private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
protected static final boolean DEBUG = true;
protected static final boolean DEBUG = false;
protected static final String TAG = "TransportControlView";
private ImageView mAlbumArt;
@@ -74,7 +76,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
private boolean mAttached;
private PendingIntent mClientIntent;
private int mTransportControlFlags;
private int mPlayState;
private int mCurrentPlayState;
private AudioManager mAudioManager;
private LockScreenWidgetCallback mWidgetCallbacks;
private IRemoteControlDisplayWeak mIRCD;
@@ -84,6 +86,11 @@ public class TransportControlView extends FrameLayout implements OnClickListener
*/
private Bundle mPopulateMetadataWhenAttached = null;
/**
* Whether to clear the interface next time it is shown (i.e. the generation id changed)
*/
private boolean mClearOnNextShow;
// This handler is required to ensure messages from IRCD are handled in sequence and on
// the UI thread.
private Handler mHandler = new Handler() {
@@ -113,15 +120,10 @@ public class TransportControlView extends FrameLayout implements OnClickListener
break;
case MSG_SET_GENERATION_ID:
if (mWidgetCallbacks != null) {
boolean clearing = msg.arg2 != 0;
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + clearing);
if (!clearing) {
mWidgetCallbacks.requestShow(TransportControlView.this);
} else {
mWidgetCallbacks.requestHide(TransportControlView.this);
}
if (msg.arg2 != 0) {
mClearOnNextShow = true; // TODO: handle this
}
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
mClientGeneration = msg.arg1;
mClientIntent = (PendingIntent) msg.obj;
break;
@@ -195,6 +197,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
super(context, attrs);
Log.v(TAG, "Create TCV " + this);
mAudioManager = new AudioManager(mContext);
mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
mIRCD = new IRemoteControlDisplayWeak(mHandler);
}
@@ -319,7 +322,7 @@ public class TransportControlView extends FrameLayout implements OnClickListener
| RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_STOP);
updatePlayPauseState(mPlayState);
updatePlayPauseState(mCurrentPlayState);
}
private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
@@ -332,12 +335,13 @@ public class TransportControlView extends FrameLayout implements OnClickListener
private void updatePlayPauseState(int state) {
if (DEBUG) Log.v(TAG,
"updatePlayPauseState(), old=" + mPlayState + ", state=" + state);
if (state == mPlayState) {
"updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
if (state == mCurrentPlayState) {
return;
}
final int imageResId;
final int imageDescId;
final boolean showIfHidden;
switch (state) {
case RemoteControlClient.PLAYSTATE_ERROR:
imageResId = com.android.internal.R.drawable.stat_sys_warning;
@@ -349,22 +353,81 @@ public class TransportControlView extends FrameLayout implements OnClickListener
case RemoteControlClient.PLAYSTATE_PLAYING:
imageResId = com.android.internal.R.drawable.ic_media_pause;
imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_BUFFERING:
imageResId = com.android.internal.R.drawable.ic_media_stop;
imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
showIfHidden = true;
break;
case RemoteControlClient.PLAYSTATE_PAUSED:
default:
imageResId = com.android.internal.R.drawable.ic_media_play;
imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
showIfHidden = false;
break;
}
mBtnPlay.setImageResource(imageResId);
mBtnPlay.setContentDescription(getResources().getString(imageDescId));
mPlayState = state;
if (showIfHidden && mWidgetCallbacks != null && !mWidgetCallbacks.isVisible(this)) {
mWidgetCallbacks.requestShow(this);
}
mCurrentPlayState = state;
}
static class SavedState extends BaseSavedState {
boolean wasShowing;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.wasShowing = in.readInt() != 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.wasShowing ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
public Parcelable onSaveInstanceState() {
if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.wasShowing = mWidgetCallbacks.isVisible(this);
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
if (ss.wasShowing) {
mWidgetCallbacks.requestShow(this);
}
}
public void onClick(View v) {

View File

@@ -49,6 +49,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -221,6 +222,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private Runnable mRecreateRunnable = new Runnable() {
public void run() {
updateScreen(mMode, true);
restoreWidgetState();
}
};
@@ -244,8 +246,20 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
// TODO: examine all widgets to derive clock status
mUpdateMonitor.reportClockVisible(true);
}
public boolean isVisible(View self) {
// TODO: this should be up to the lockscreen to determine if the view
// is currently showing. The idea is it can be used for the widget to
// avoid doing work if it's not visible. For now just returns the view's
// actual visibility.
return self.getVisibility() == View.VISIBLE;
}
};
private TransportControlView mTransportControlView;
private Parcelable mSavedState;
/**
* @return Whether we are stuck on the lock screen because the sim is
* missing.
@@ -365,6 +379,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
public void keyguardDone(boolean authenticated) {
getCallback().keyguardDone(authenticated);
mSavedState = null; // clear state so we re-establish when locked again
}
public void keyguardDoneDrawing() {
@@ -528,6 +543,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
((KeyguardScreen) mUnlockScreen).onPause();
}
saveWidgetState();
// When screen is turned off, need to unbind from FaceLock service if using FaceLock
stopAndUnbindFromFaceLock();
}
@@ -558,8 +575,28 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mScreenOn = true;
runFaceLock = mWindowFocused;
}
show();
if(runFaceLock) activateFaceLockIfAble();
restoreWidgetState();
if (runFaceLock) activateFaceLockIfAble();
}
private void saveWidgetState() {
if (mTransportControlView != null) {
if (DEBUG) Log.v(TAG, "Saving widget state");
mSavedState = mTransportControlView.onSaveInstanceState();
}
}
private void restoreWidgetState() {
if (mTransportControlView != null) {
if (DEBUG) Log.v(TAG, "Restoring widget state");
if (mSavedState != null) {
mTransportControlView.onRestoreInstanceState(mSavedState);
}
}
}
/** Unbind from facelock if something covers this window (such as an alarm)
@@ -643,6 +680,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
mConfiguration = newConfig;
if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
saveWidgetState();
removeCallbacks(mRecreateRunnable);
post(mRecreateRunnable);
}
@@ -895,13 +933,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
}
private void initializeTransportControlView(View view) {
TransportControlView tcv = (TransportControlView) view.findViewById(R.id.transport);
if (tcv == null) {
mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
if (mTransportControlView == null) {
if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
} else {
mUpdateMonitor.reportClockVisible(true);
tcv.setVisibility(View.GONE); // hide until it requests being shown.
tcv.setCallback(mWidgetCallback);
mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
mTransportControlView.setCallback(mWidgetCallback);
}
}