Show keyguard scrim on external displays while keyguard showing
Fixes bug 11562369
Change-Id: I577f9d3683e62689954b4640601b3f360b78cb31
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
new file mode 100644
index 0000000..6bcbd6c
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard;
+
+import android.app.Presentation;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.graphics.Point;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteInfo;
+import android.os.Bundle;
+import android.util.Slog;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManager;
+
+public class KeyguardDisplayManager {
+ protected static final String TAG = "KeyguardDisplayManager";
+ private static boolean DEBUG = KeyguardViewMediator.DEBUG;
+ Presentation mPresentation;
+ private MediaRouter mMediaRouter;
+ private Context mContext;
+ private boolean mShowing;
+
+ KeyguardDisplayManager(Context context) {
+ mContext = context;
+ mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ }
+
+ void show() {
+ if (!mShowing) {
+ if (DEBUG) Slog.v(TAG, "show");
+ mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
+ mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+ updateDisplays(true);
+ }
+ mShowing = true;
+ }
+
+ void hide() {
+ if (mShowing) {
+ if (DEBUG) Slog.v(TAG, "hide");
+ mMediaRouter.removeCallback(mMediaRouterCallback);
+ updateDisplays(false);
+ }
+ mShowing = false;
+ }
+
+ private final MediaRouter.SimpleCallback mMediaRouterCallback =
+ new MediaRouter.SimpleCallback() {
+ @Override
+ public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
+ if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
+ updateDisplays(mShowing);
+ }
+
+ @Override
+ public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
+ if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
+ updateDisplays(mShowing);
+ }
+
+ @Override
+ public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
+ if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
+ updateDisplays(mShowing);
+ }
+ };
+
+ private OnDismissListener mOnDismissListener = new OnDismissListener() {
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mPresentation = null;
+ }
+ };
+
+ protected void updateDisplays(boolean showing) {
+ if (showing) {
+ MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
+ MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
+ boolean useDisplay = route != null
+ && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
+ Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null;
+
+ if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
+ if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay());
+ mPresentation.dismiss();
+ mPresentation = null;
+ }
+
+ if (mPresentation == null && presentationDisplay != null) {
+ if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay);
+ mPresentation = new KeyguardPresentation(mContext, presentationDisplay);
+ mPresentation.setOnDismissListener(mOnDismissListener);
+ try {
+ mPresentation.show();
+ } catch (WindowManager.InvalidDisplayException ex) {
+ Slog.w(TAG, "Invalid display:", ex);
+ mPresentation = null;
+ }
+ }
+ } else {
+ if (mPresentation != null) {
+ mPresentation.dismiss();
+ mPresentation = null;
+ }
+ }
+ }
+
+ private final static class KeyguardPresentation extends Presentation {
+ private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
+ private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
+ private View mClock;
+ private int mUsableWidth;
+ private int mUsableHeight;
+ private int mMarginTop;
+ private int mMarginLeft;
+ Runnable mMoveTextRunnable = new Runnable() {
+ @Override
+ public void run() {
+ int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth()));
+ int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight()));
+ mClock.setTranslationX(x);
+ mClock.setTranslationY(y);
+ mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT);
+ }
+ };
+
+ public KeyguardPresentation(Context context, Display display) {
+ super(context, display);
+ getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ }
+
+ public void onDetachedFromWindow() {
+ mClock.removeCallbacks(mMoveTextRunnable);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Point p = new Point();
+ getDisplay().getSize(p);
+ mUsableWidth = VIDEO_SAFE_REGION * p.x/100;
+ mUsableHeight = VIDEO_SAFE_REGION * p.y/100;
+ mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200;
+ mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200;
+
+ setContentView(R.layout.keyguard_presentation);
+ mClock = findViewById(R.id.clock);
+
+ // Avoid screen burn in
+ mClock.post(mMoveTextRunnable);
+ }
+ }
+}