Merge "Fix 5358124: Better transport control visibility management in lock screen" into ics-mr0
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user