Keyguard transport controls: fullscreen art

When the transport controls are active, set the relevant art as a
fullscreen background for the keyguard.

Change-Id: I1e8a87f242153a2a2c5bf94dbd15f0fd3e07dde3
This commit is contained in:
Adam Powell
2013-09-27 17:43:53 -07:00
parent 1ae85153c8
commit 43a372f38a
7 changed files with 101 additions and 21 deletions

View File

@@ -22,22 +22,16 @@
android:gravity="center_horizontal"
android:id="@+id/keyguard_transport_control">
<!-- FrameLayout used as scrim to show between album art and buttons -->
<FrameLayout
<!-- Use ImageView for its cropping features; otherwise could be android:background -->
<ImageView
android:id="@+id/albumart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@drawable/ic_lockscreen_player_background"
android:contentDescription="@string/keygaurd_accessibility_media_controls">
<!-- Use ImageView for its cropping features; otherwise could be android:background -->
<ImageView
android:id="@+id/albumart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill"
android:scaleType="centerCrop"
android:adjustViewBounds="false"
/>
</FrameLayout>
android:layout_gravity="fill"
android:scaleType="centerCrop"
android:adjustViewBounds="false"
android:contentDescription="@string/keygaurd_accessibility_media_controls" />
<LinearLayout
android:orientation="vertical"

View File

@@ -1483,6 +1483,7 @@ public class KeyguardHostView extends KeyguardViewBase {
if (DEBUGXPORT) Log.v(TAG, "remove transport");
mAppWidgetContainer.removeWidget(getOrCreateTransportControl());
mTransportControl = null;
KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(null);
}
}

View File

@@ -36,6 +36,7 @@ import android.text.Spannable;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -98,11 +99,9 @@ public class KeyguardTransportControlView extends FrameLayout implements OnClick
case MSG_SET_ARTWORK:
if (mClientGeneration == msg.arg1) {
if (mMetadata.bitmap != null) {
mMetadata.bitmap.recycle();
}
mMetadata.bitmap = (Bitmap) msg.obj;
mAlbumArt.setImageBitmap(mMetadata.bitmap);
KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(
mMetadata.bitmap);
}
break;
@@ -223,7 +222,8 @@ public class KeyguardTransportControlView extends FrameLayout implements OnClick
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) {
if (mAttached) {
int dim = Math.min(512, Math.max(w, h));
final DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
int dim = Math.max(dm.widthPixels, dm.heightPixels);
if (DEBUG) Log.v(TAG, "TCV uses bitmap size=" + dim);
mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim);
}
@@ -300,7 +300,8 @@ public class KeyguardTransportControlView extends FrameLayout implements OnClick
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mAlbumArt.setImageBitmap(mMetadata.bitmap);
KeyguardUpdateMonitor.getInstance(getContext()).dispatchSetBackground(
mMetadata.bitmap);
final int flags = mTransportControlFlags;
setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);

View File

@@ -407,6 +407,20 @@ public class KeyguardUpdateMonitor {
return sInstance;
}
/**
* IMPORTANT: Must be called from UI thread.
*/
public void dispatchSetBackground(Bitmap bmp) {
if (DEBUG) Log.d(TAG, "dispatchSetBackground");
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onSetBackground(bmp);
}
}
}
protected void handleSetGenerationId(int clientGeneration, boolean clearing, PendingIntent p) {
mDisplayClientState.clientGeneration = clientGeneration;
mDisplayClientState.clearing = clearing;

View File

@@ -17,6 +17,7 @@ package com.android.keyguard;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.graphics.Bitmap;
import android.media.AudioManager;
import com.android.internal.telephony.IccCardConstants;
@@ -135,4 +136,8 @@ class KeyguardUpdateMonitorCallback {
* Called when the emergency call button is pressed.
*/
void onEmergencyCallAction() { }
public void onSetBackground(Bitmap bitmap) {
// THIS SPACE FOR RENT
}
}

View File

@@ -16,6 +16,9 @@
package com.android.keyguard;
import android.app.PendingIntent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.widget.LockPatternUtils;
@@ -77,6 +80,14 @@ public class KeyguardViewManager {
private boolean mScreenOn = false;
private LockPatternUtils mLockPatternUtils;
private KeyguardUpdateMonitorCallback mBackgroundChanger = new KeyguardUpdateMonitorCallback() {
@Override
public void onSetBackground(Bitmap bmp) {
mKeyguardHost.setCustomBackground(bmp != null ?
new BitmapDrawable(mContext.getResources(), bmp) : null);
}
};
public interface ShowListener {
void onShown(IBinder windowToken);
};
@@ -140,11 +151,25 @@ public class KeyguardViewManager {
class ViewManagerHost extends FrameLayout {
private static final int BACKGROUND_COLOR = 0x70000000;
private Drawable mCustomBackground;
// This is a faster way to draw the background on devices without hardware acceleration
private final Drawable mBackgroundDrawable = new Drawable() {
@Override
public void draw(Canvas canvas) {
canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
if (mCustomBackground != null) {
final Rect bounds = mCustomBackground.getBounds();
final int vWidth = getWidth();
final int vHeight = getHeight();
final int restore = canvas.save();
canvas.translate(-(bounds.width() - vWidth) / 2,
-(bounds.height() - vHeight) / 2);
mCustomBackground.draw(canvas);
canvas.restoreToCount(restore);
} else {
canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
}
}
@Override
@@ -166,6 +191,40 @@ public class KeyguardViewManager {
setBackground(mBackgroundDrawable);
}
public void setCustomBackground(Drawable d) {
mCustomBackground = d;
if (d != null) {
d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER);
}
computeCustomBackgroundBounds();
invalidate();
}
private void computeCustomBackgroundBounds() {
if (mCustomBackground == null) return; // Nothing to do
if (!isLaidOut()) return; // We'll do this later
final int bgWidth = mCustomBackground.getIntrinsicWidth();
final int bgHeight = mCustomBackground.getIntrinsicHeight();
final int vWidth = getWidth();
final int vHeight = getHeight();
final float bgAspect = (float) bgWidth / bgHeight;
final float vAspect = (float) vWidth / vHeight;
if (bgAspect > vAspect) {
mCustomBackground.setBounds(0, 0, (int) (vHeight * bgAspect), vHeight);
} else {
mCustomBackground.setBounds(0, 0, vWidth, (int) (vWidth / bgAspect));
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
computeCustomBackgroundBounds();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -239,9 +298,12 @@ public class KeyguardViewManager {
lp.setTitle("Keyguard");
mWindowLayoutParams = lp;
mViewManager.addView(mKeyguardHost, lp);
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
}
if (force || mKeyguardView == null) {
mKeyguardHost.setCustomBackground(null);
mKeyguardHost.removeAllViews();
inflateKeyguardView(options);
mKeyguardView.requestFocus();
@@ -428,6 +490,8 @@ public class KeyguardViewManager {
public void run() {
synchronized (KeyguardViewManager.this) {
lastView.cleanUp();
// Let go of any large bitmaps.
mKeyguardHost.setCustomBackground(null);
mKeyguardHost.removeView(lastView);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.keyguard;
import android.graphics.Bitmap;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardShowCallback;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;