1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.keyguard; 17 18 import android.app.Presentation; 19 import android.content.Context; 20 import android.content.DialogInterface; 21 import android.content.DialogInterface.OnDismissListener; 22 import android.graphics.Point; 23 import android.media.MediaRouter; 24 import android.media.MediaRouter.RouteInfo; 25 import android.os.Bundle; 26 import android.util.Slog; 27 import android.view.Display; 28 import android.view.View; 29 import android.view.WindowManager; 30 31 public class KeyguardDisplayManager { 32 protected static final String TAG = "KeyguardDisplayManager"; 33 private static boolean DEBUG = KeyguardConstants.DEBUG; 34 Presentation mPresentation; 35 private MediaRouter mMediaRouter; 36 private Context mContext; 37 private boolean mShowing; 38 KeyguardDisplayManager(Context context)39 public KeyguardDisplayManager(Context context) { 40 mContext = context; 41 mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE); 42 } 43 show()44 public void show() { 45 if (!mShowing) { 46 if (DEBUG) Slog.v(TAG, "show"); 47 mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, 48 mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); 49 updateDisplays(true); 50 } 51 mShowing = true; 52 } 53 hide()54 public void hide() { 55 if (mShowing) { 56 if (DEBUG) Slog.v(TAG, "hide"); 57 mMediaRouter.removeCallback(mMediaRouterCallback); 58 updateDisplays(false); 59 } 60 mShowing = false; 61 } 62 63 private final MediaRouter.SimpleCallback mMediaRouterCallback = 64 new MediaRouter.SimpleCallback() { 65 @Override 66 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { 67 if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info); 68 updateDisplays(mShowing); 69 } 70 71 @Override 72 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { 73 if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info); 74 updateDisplays(mShowing); 75 } 76 77 @Override 78 public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) { 79 if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info); 80 updateDisplays(mShowing); 81 } 82 }; 83 84 private OnDismissListener mOnDismissListener = new OnDismissListener() { 85 86 @Override 87 public void onDismiss(DialogInterface dialog) { 88 mPresentation = null; 89 } 90 }; 91 updateDisplays(boolean showing)92 protected void updateDisplays(boolean showing) { 93 if (showing) { 94 MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute( 95 MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY); 96 boolean useDisplay = route != null 97 && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE; 98 Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null; 99 100 if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { 101 if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay()); 102 mPresentation.dismiss(); 103 mPresentation = null; 104 } 105 106 if (mPresentation == null && presentationDisplay != null) { 107 if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay); 108 mPresentation = new KeyguardPresentation(mContext, presentationDisplay, 109 R.style.keyguard_presentation_theme); 110 mPresentation.setOnDismissListener(mOnDismissListener); 111 try { 112 mPresentation.show(); 113 } catch (WindowManager.InvalidDisplayException ex) { 114 Slog.w(TAG, "Invalid display:", ex); 115 mPresentation = null; 116 } 117 } 118 } else { 119 if (mPresentation != null) { 120 mPresentation.dismiss(); 121 mPresentation = null; 122 } 123 } 124 } 125 126 private final static class KeyguardPresentation extends Presentation { 127 private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height 128 private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s 129 private View mClock; 130 private int mUsableWidth; 131 private int mUsableHeight; 132 private int mMarginTop; 133 private int mMarginLeft; 134 Runnable mMoveTextRunnable = new Runnable() { 135 @Override 136 public void run() { 137 int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth())); 138 int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight())); 139 mClock.setTranslationX(x); 140 mClock.setTranslationY(y); 141 mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT); 142 } 143 }; 144 KeyguardPresentation(Context context, Display display, int theme)145 public KeyguardPresentation(Context context, Display display, int theme) { 146 super(context, display, theme); 147 getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 148 } 149 150 @Override onDetachedFromWindow()151 public void onDetachedFromWindow() { 152 mClock.removeCallbacks(mMoveTextRunnable); 153 } 154 155 @Override onCreate(Bundle savedInstanceState)156 protected void onCreate(Bundle savedInstanceState) { 157 super.onCreate(savedInstanceState); 158 159 Point p = new Point(); 160 getDisplay().getSize(p); 161 mUsableWidth = VIDEO_SAFE_REGION * p.x/100; 162 mUsableHeight = VIDEO_SAFE_REGION * p.y/100; 163 mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; 164 mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200; 165 166 setContentView(R.layout.keyguard_presentation); 167 mClock = findViewById(R.id.clock); 168 169 // Avoid screen burn in 170 mClock.post(mMoveTextRunnable); 171 } 172 } 173 } 174