Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a59c7e3 authored by Jim Miller's avatar Jim Miller Committed by Android (Google) Code Review
Browse files

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

parents ed37b1bf 4e6d3582
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+77 −14
Original line number Diff line number Diff line
@@ -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) {
+43 −5
Original line number Diff line number Diff line
@@ -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,10 +575,30 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
            mScreenOn = true;
            runFaceLock = mWindowFocused;
        }

        show();

        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)
     * bind to facelock if the lockscreen window just came into focus, and the screen is on
     */
@@ -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);
        }
    }