am 74bc9b68: Merge "Implement music and user priority scheme in keyguard" into jb-mr1-dev

* commit '74bc9b68510d8e88fb1c806313aad3f35543202b':
  Implement music and user priority scheme in keyguard
This commit is contained in:
Jim Miller
2012-10-09 15:15:13 -07:00
committed by Android Git Automerger
3 changed files with 140 additions and 49 deletions

View File

@ -33,6 +33,8 @@ import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Looper; import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserManager; import android.os.UserManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@ -43,12 +45,14 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.View.BaseSavedState;
import android.view.animation.AnimationUtils; import android.view.animation.AnimationUtils;
import android.widget.RemoteViews.OnClickHandler; import android.widget.RemoteViews.OnClickHandler;
import android.widget.ViewFlipper; import android.widget.ViewFlipper;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.internal.policy.impl.keyguard.KeyguardTransportControlView.SavedState;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
import java.io.File; import java.io.File;
@ -64,6 +68,10 @@ public class KeyguardHostView extends KeyguardViewBase {
static final int APPWIDGET_HOST_ID = 0x4B455947; static final int APPWIDGET_HOST_ID = 0x4B455947;
private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs"; private static final String KEYGUARD_WIDGET_PREFS = "keyguard_widget_prefs";
private static final int TRANSPORT_GONE = 0;
private static final int TRANSPORT_INVISIBLE = 1;
private static final int TRANSPORT_VISIBLE = 2;
private AppWidgetHost mAppWidgetHost; private AppWidgetHost mAppWidgetHost;
private KeyguardWidgetRegion mAppWidgetRegion; private KeyguardWidgetRegion mAppWidgetRegion;
private KeyguardWidgetPager mAppWidgetContainer; private KeyguardWidgetPager mAppWidgetContainer;
@ -83,10 +91,12 @@ public class KeyguardHostView extends KeyguardViewBase {
private KeyguardSecurityModel mSecurityModel; private KeyguardSecurityModel mSecurityModel;
private Rect mTempRect = new Rect(); private Rect mTempRect = new Rect();
private int mTransportState = TRANSPORT_GONE;
/*package*/ interface TransportCallback { /*package*/ interface TransportCallback {
void hide(); void onListenerDetached();
void show(); void onListenerAttached();
void onPlayStateChanged();
} }
/*package*/ interface UserSwitcherCallback { /*package*/ interface UserSwitcherCallback {
@ -185,7 +195,7 @@ public class KeyguardHostView extends KeyguardViewBase {
mAppWidgetHost.startListening(); mAppWidgetHost.startListening();
maybePopulateWidgets(); maybePopulateWidgets();
disableStatusViewInteraction(); disableStatusViewInteraction();
showAppropriateWidgetPage(); post(mSwitchPageRunnable);
} }
private void disableStatusViewInteraction() { private void disableStatusViewInteraction() {
@ -712,7 +722,7 @@ public class KeyguardHostView extends KeyguardViewBase {
private void addDefaultWidgets() { private void addDefaultWidgets() {
LayoutInflater inflater = LayoutInflater.from(mContext); LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.keyguard_status_view, mAppWidgetContainer, true); inflater.inflate(R.layout.keyguard_status_view, mAppWidgetContainer, true);
inflater.inflate(R.layout.keyguard_transport_control_view, mAppWidgetContainer, true); inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
inflateAndAddUserSelectorWidgetIfNecessary(); inflateAndAddUserSelectorWidgetIfNecessary();
initializeTransportControl(); initializeTransportControl();
@ -721,16 +731,16 @@ public class KeyguardHostView extends KeyguardViewBase {
private void initializeTransportControl() { private void initializeTransportControl() {
mTransportControl = mTransportControl =
(KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control); (KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control);
mTransportControl.setVisibility(View.GONE);
// This code manages showing/hiding the transport control. We keep it around and only // This code manages showing/hiding the transport control. We keep it around and only
// add it to the hierarchy if it needs to be present. // add it to the hierarchy if it needs to be present.
if (mTransportControl != null) { if (mTransportControl != null) {
mTransportControl.setKeyguardCallback(new TransportCallback() { mTransportControl.setKeyguardCallback(new TransportCallback() {
boolean mSticky = false;
@Override @Override
public void hide() { public void onListenerDetached() {
int page = getWidgetPosition(R.id.keyguard_transport_control); int page = getWidgetPosition(R.id.keyguard_transport_control);
if (page != -1 && !mSticky) { if (page != -1) {
if (page == mAppWidgetContainer.getCurrentPage()) { if (page == mAppWidgetContainer.getCurrentPage()) {
// Switch back to clock view if music was showing. // Switch back to clock view if music was showing.
mAppWidgetContainer mAppWidgetContainer
@ -741,20 +751,23 @@ public class KeyguardHostView extends KeyguardViewBase {
// from AudioManager // from AudioManager
KeyguardHostView.this.addView(mTransportControl); KeyguardHostView.this.addView(mTransportControl);
mTransportControl.setVisibility(View.GONE); mTransportControl.setVisibility(View.GONE);
mTransportState = TRANSPORT_GONE;
} }
} }
@Override @Override
public void show() { public void onListenerAttached() {
if (getWidgetPosition(R.id.keyguard_transport_control) == -1) { if (getWidgetPosition(R.id.keyguard_transport_control) == -1) {
KeyguardHostView.this.removeView(mTransportControl); KeyguardHostView.this.removeView(mTransportControl);
mAppWidgetContainer.addView(mTransportControl, mAppWidgetContainer.addView(mTransportControl, 0);
getWidgetPosition(R.id.keyguard_status_view) + 1);
mTransportControl.setVisibility(View.VISIBLE); mTransportControl.setVisibility(View.VISIBLE);
// Once shown, leave it showing
mSticky = true;
} }
} }
@Override
public void onPlayStateChanged() {
mTransportControl.post(mSwitchPageRunnable);
}
}); });
} }
} }
@ -796,12 +809,87 @@ public class KeyguardHostView extends KeyguardViewBase {
} }
} }
private void showAppropriateWidgetPage() { Runnable mSwitchPageRunnable = new Runnable() {
int page = mAppWidgetContainer.indexOfChild(findViewById(R.id.keyguard_status_view)); @Override
if (mAppWidgetContainer.indexOfChild(mTransportControl) != -1) { public void run() {
page = mAppWidgetContainer.indexOfChild(mTransportControl); showAppropriateWidgetPage();
} }
mAppWidgetContainer.setCurrentPage(page); };
static class SavedState extends BaseSavedState {
int transportState;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.transportState = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.transportState);
}
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() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.transportState = mTransportState;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mTransportState = ss.transportState;
post(mSwitchPageRunnable);
}
private void showAppropriateWidgetPage() {
// The following sets the priority for showing widgets. Transport should be shown if
// music is playing, followed by the multi-user widget if enabled, followed by the
// status widget.
final int pageToShow;
if (mTransportControl.isMusicPlaying() || mTransportState == TRANSPORT_VISIBLE) {
mTransportState = TRANSPORT_VISIBLE;
pageToShow = mAppWidgetContainer.indexOfChild(mTransportControl);
} else {
UserManager mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
final View multiUserView = findViewById(R.id.keyguard_multi_user_selector);
final int multiUserPosition = mAppWidgetContainer.indexOfChild(multiUserView);
if (multiUserPosition != -1 && mUm.getUsers(true).size() > 1) {
pageToShow = multiUserPosition;
} else {
final View statusView = findViewById(R.id.keyguard_status_view);
pageToShow = mAppWidgetContainer.indexOfChild(statusView);
}
if (mTransportState == TRANSPORT_VISIBLE) {
mTransportState = TRANSPORT_INVISIBLE;
}
}
mAppWidgetContainer.setCurrentPage(pageToShow);
} }
private void inflateAndAddUserSelectorWidgetIfNecessary() { private void inflateAndAddUserSelectorWidgetIfNecessary() {

View File

@ -42,7 +42,6 @@ import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -59,7 +58,7 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
private static final int MSG_SET_GENERATION_ID = 104; private static final int MSG_SET_GENERATION_ID = 104;
private static final int MAXDIM = 512; private static final int MAXDIM = 512;
private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
protected static final boolean DEBUG = false; protected static final boolean DEBUG = true;
protected static final String TAG = "TransportControlView"; protected static final String TAG = "TransportControlView";
private ImageView mAlbumArt; private ImageView mAlbumArt;
@ -75,6 +74,7 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
private int mCurrentPlayState; private int mCurrentPlayState;
private AudioManager mAudioManager; private AudioManager mAudioManager;
private IRemoteControlDisplayWeak mIRCD; private IRemoteControlDisplayWeak mIRCD;
private boolean mMusicClientPresent = true;
/** /**
* The metadata which should be populated into the view once we've been attached * The metadata which should be populated into the view once we've been attached
@ -112,7 +112,9 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
case MSG_SET_GENERATION_ID: case MSG_SET_GENERATION_ID:
if (msg.arg2 != 0) { if (msg.arg2 != 0) {
// This means nobody is currently registered. Hide the view. // This means nobody is currently registered. Hide the view.
hide(); onListenerDetached();
} else {
onListenerAttached();
} }
if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2); if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
mClientGeneration = msg.arg1; mClientGeneration = msg.arg1;
@ -193,28 +195,26 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
mIRCD = new IRemoteControlDisplayWeak(mHandler); mIRCD = new IRemoteControlDisplayWeak(mHandler);
} }
protected void hide() { protected void onListenerDetached() {
if (DEBUG) Log.v(TAG, "Transport was told to hide"); mMusicClientPresent = false;
if (DEBUG) Log.v(TAG, "onListenerDetached()");
if (mTransportCallback != null) { if (mTransportCallback != null) {
mTransportCallback.hide(); mTransportCallback.onListenerDetached();
} else { } else {
Log.w(TAG, "Hide music, but callback wasn't set"); Log.w(TAG, "onListenerDetached: no callback");
} }
} }
private void show() { private void onListenerAttached() {
if (DEBUG) Log.v(TAG, "Transport was told to show"); mMusicClientPresent = true;
if (DEBUG) Log.v(TAG, "onListenerAttached()");
if (mTransportCallback != null) { if (mTransportCallback != null) {
mTransportCallback.show(); mTransportCallback.onListenerAttached();
} else { } else {
Log.w(TAG, "Show music, but callback wasn't set"); Log.w(TAG, "onListenerAttached(): no callback");
} }
} }
private void userActivity() {
// TODO Auto-generated method stub
}
private void updateTransportControls(int transportControlFlags) { private void updateTransportControls(int transportControlFlags) {
mTransportControlFlags = transportControlFlags; mTransportControlFlags = transportControlFlags;
} }
@ -341,6 +341,11 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
updatePlayPauseState(mCurrentPlayState); updatePlayPauseState(mCurrentPlayState);
} }
public boolean isMusicPlaying() {
return mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING
|| mCurrentPlayState == RemoteControlClient.PLAYSTATE_BUFFERING;
}
private static void setVisibilityBasedOnFlag(View view, int flags, int flag) { private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
if ((flags & flag) != 0) { if ((flags & flag) != 0) {
view.setVisibility(View.VISIBLE); view.setVisibility(View.VISIBLE);
@ -357,7 +362,6 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
} }
final int imageResId; final int imageResId;
final int imageDescId; final int imageDescId;
boolean showIfHidden = false;
switch (state) { switch (state) {
case RemoteControlClient.PLAYSTATE_ERROR: case RemoteControlClient.PLAYSTATE_ERROR:
imageResId = com.android.internal.R.drawable.stat_sys_warning; imageResId = com.android.internal.R.drawable.stat_sys_warning;
@ -369,32 +373,27 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
case RemoteControlClient.PLAYSTATE_PLAYING: case RemoteControlClient.PLAYSTATE_PLAYING:
imageResId = com.android.internal.R.drawable.ic_media_pause; imageResId = com.android.internal.R.drawable.ic_media_pause;
imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description; imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
showIfHidden = true;
break; break;
case RemoteControlClient.PLAYSTATE_BUFFERING: case RemoteControlClient.PLAYSTATE_BUFFERING:
imageResId = com.android.internal.R.drawable.ic_media_stop; imageResId = com.android.internal.R.drawable.ic_media_stop;
imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description; imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
showIfHidden = true;
break; break;
case RemoteControlClient.PLAYSTATE_PAUSED: case RemoteControlClient.PLAYSTATE_PAUSED:
default: default:
imageResId = com.android.internal.R.drawable.ic_media_play; imageResId = com.android.internal.R.drawable.ic_media_play;
imageDescId = com.android.internal.R.string.lockscreen_transport_play_description; imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
showIfHidden = false;
break; break;
} }
mBtnPlay.setImageResource(imageResId); mBtnPlay.setImageResource(imageResId);
mBtnPlay.setContentDescription(getResources().getString(imageDescId)); mBtnPlay.setContentDescription(getResources().getString(imageDescId));
if (showIfHidden) {
show();
}
mCurrentPlayState = state; mCurrentPlayState = state;
mTransportCallback.onPlayStateChanged();
} }
static class SavedState extends BaseSavedState { static class SavedState extends BaseSavedState {
boolean wasShowing; boolean clientPresent;
SavedState(Parcelable superState) { SavedState(Parcelable superState) {
super(superState); super(superState);
@ -402,13 +401,13 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
private SavedState(Parcel in) { private SavedState(Parcel in) {
super(in); super(in);
this.wasShowing = in.readInt() != 0; this.clientPresent = in.readInt() != 0;
} }
@Override @Override
public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags); super.writeToParcel(out, flags);
out.writeInt(this.wasShowing ? 1 : 0); out.writeInt(this.clientPresent ? 1 : 0);
} }
public static final Parcelable.Creator<SavedState> CREATOR public static final Parcelable.Creator<SavedState> CREATOR
@ -425,24 +424,23 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
@Override @Override
public Parcelable onSaveInstanceState() { public Parcelable onSaveInstanceState() {
if (DEBUG) Log.v(TAG, "onSaveInstanceState()");
Parcelable superState = super.onSaveInstanceState(); Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState); SavedState ss = new SavedState(superState);
ss.wasShowing = getVisibility() == View.VISIBLE; ss.clientPresent = mMusicClientPresent;
return ss; return ss;
} }
@Override @Override
public void onRestoreInstanceState(Parcelable state) { public void onRestoreInstanceState(Parcelable state) {
if (DEBUG) Log.v(TAG, "onRestoreInstanceState()");
if (!(state instanceof SavedState)) { if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state); super.onRestoreInstanceState(state);
return; return;
} }
SavedState ss = (SavedState) state; SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState()); super.onRestoreInstanceState(ss.getSuperState());
if (ss.wasShowing) { if (ss.clientPresent) {
show(); if (DEBUG) Log.v(TAG, "Reattaching client because it was attached");
onListenerAttached();
} }
} }
@ -458,7 +456,6 @@ public class KeyguardTransportControlView extends KeyguardWidgetFrame implements
} }
if (keyCode != -1) { if (keyCode != -1) {
sendMediaButtonClick(keyCode); sendMediaButtonClick(keyCode);
userActivity();
} }
} }

View File

@ -48,7 +48,7 @@ import com.android.internal.widget.LockPatternUtils;
* reported to this class by the current {@link KeyguardViewBase}. * reported to this class by the current {@link KeyguardViewBase}.
*/ */
public class KeyguardViewManager { public class KeyguardViewManager {
private final static boolean DEBUG = false; private final static boolean DEBUG = true;
private static String TAG = "KeyguardViewManager"; private static String TAG = "KeyguardViewManager";
public static boolean USE_UPPER_CASE = true; public static boolean USE_UPPER_CASE = true;
@ -359,6 +359,12 @@ public class KeyguardViewManager {
if (mKeyguardHost != null) { if (mKeyguardHost != null) {
mKeyguardHost.setVisibility(View.GONE); mKeyguardHost.setVisibility(View.GONE);
// We really only want to preserve keyguard state for configuration changes. Hence
// we should clear state of widgets (e.g. Music) when we hide keyguard so it can
// start with a fresh state when we return.
mStateContainer.clear();
// Don't do this right away, so we can let the view continue to animate // Don't do this right away, so we can let the view continue to animate
// as it goes away. // as it goes away.
if (mKeyguardView != null) { if (mKeyguardView != null) {