blob: 55f965c3511e329d33c725a3e5d3ca3224cc9aca [file] [log] [blame]
Jim Miller31921482013-11-06 20:43:55 -08001/*
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 */
16package com.android.keyguard;
17
18import android.app.Presentation;
19import android.content.Context;
20import android.content.DialogInterface;
21import android.content.DialogInterface.OnDismissListener;
22import android.graphics.Point;
23import android.media.MediaRouter;
24import android.media.MediaRouter.RouteInfo;
25import android.os.Bundle;
26import android.util.Slog;
27import android.view.Display;
28import android.view.View;
29import android.view.WindowManager;
30
31public class KeyguardDisplayManager {
32 protected static final String TAG = "KeyguardDisplayManager";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010033 private static boolean DEBUG = KeyguardConstants.DEBUG;
Jim Miller31921482013-11-06 20:43:55 -080034 Presentation mPresentation;
35 private MediaRouter mMediaRouter;
36 private Context mContext;
37 private boolean mShowing;
38
Jorim Jaggi5cf17872014-03-26 18:31:48 +010039 public KeyguardDisplayManager(Context context) {
Jim Miller31921482013-11-06 20:43:55 -080040 mContext = context;
41 mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
42 }
43
Jorim Jaggi5cf17872014-03-26 18:31:48 +010044 public void show() {
Jim Miller31921482013-11-06 20:43:55 -080045 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
Jorim Jaggi5cf17872014-03-26 18:31:48 +010054 public void hide() {
Jim Miller31921482013-11-06 20:43:55 -080055 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
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 mPresentation.setOnDismissListener(mOnDismissListener);
110 try {
111 mPresentation.show();
112 } catch (WindowManager.InvalidDisplayException ex) {
113 Slog.w(TAG, "Invalid display:", ex);
114 mPresentation = null;
115 }
116 }
117 } else {
118 if (mPresentation != null) {
119 mPresentation.dismiss();
120 mPresentation = null;
121 }
122 }
123 }
124
125 private final static class KeyguardPresentation extends Presentation {
126 private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
127 private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
128 private View mClock;
129 private int mUsableWidth;
130 private int mUsableHeight;
131 private int mMarginTop;
132 private int mMarginLeft;
133 Runnable mMoveTextRunnable = new Runnable() {
134 @Override
135 public void run() {
136 int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth()));
137 int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight()));
138 mClock.setTranslationX(x);
139 mClock.setTranslationY(y);
140 mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT);
141 }
142 };
143
144 public KeyguardPresentation(Context context, Display display) {
145 super(context, display);
146 getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
147 }
148
149 public void onDetachedFromWindow() {
150 mClock.removeCallbacks(mMoveTextRunnable);
151 }
152
153 @Override
154 protected void onCreate(Bundle savedInstanceState) {
155 super.onCreate(savedInstanceState);
156
157 Point p = new Point();
158 getDisplay().getSize(p);
159 mUsableWidth = VIDEO_SAFE_REGION * p.x/100;
160 mUsableHeight = VIDEO_SAFE_REGION * p.y/100;
161 mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200;
162 mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200;
163
164 setContentView(R.layout.keyguard_presentation);
165 mClock = findViewById(R.id.clock);
166
167 // Avoid screen burn in
168 mClock.post(mMoveTextRunnable);
169 }
170 }
171}