blob: 2bc0e45c725d71848e33ce33175949e8d14877f0 [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
David Stevens53a39ea2017-08-23 18:41:49 -070018import static android.view.Display.INVALID_DISPLAY;
19
Jim Miller31921482013-11-06 20:43:55 -080020import android.app.Presentation;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.content.DialogInterface.OnDismissListener;
24import android.graphics.Point;
25import android.media.MediaRouter;
26import android.media.MediaRouter.RouteInfo;
27import android.os.Bundle;
28import android.util.Slog;
29import android.view.Display;
30import android.view.View;
31import android.view.WindowManager;
32
David Stevens53a39ea2017-08-23 18:41:49 -070033// TODO(multi-display): Support multiple external displays
Jim Miller31921482013-11-06 20:43:55 -080034public class KeyguardDisplayManager {
35 protected static final String TAG = "KeyguardDisplayManager";
Jorim Jaggi5cf17872014-03-26 18:31:48 +010036 private static boolean DEBUG = KeyguardConstants.DEBUG;
David Stevens53a39ea2017-08-23 18:41:49 -070037
38 private final ViewMediatorCallback mCallback;
39 private final MediaRouter mMediaRouter;
40 private final Context mContext;
41
Jim Miller31921482013-11-06 20:43:55 -080042 Presentation mPresentation;
Jim Miller31921482013-11-06 20:43:55 -080043 private boolean mShowing;
44
David Stevens53a39ea2017-08-23 18:41:49 -070045 public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
Jim Miller31921482013-11-06 20:43:55 -080046 mContext = context;
David Stevens53a39ea2017-08-23 18:41:49 -070047 mCallback = callback;
Jim Miller31921482013-11-06 20:43:55 -080048 mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
49 }
50
Jorim Jaggi5cf17872014-03-26 18:31:48 +010051 public void show() {
Jim Miller31921482013-11-06 20:43:55 -080052 if (!mShowing) {
53 if (DEBUG) Slog.v(TAG, "show");
54 mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
55 mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
56 updateDisplays(true);
57 }
58 mShowing = true;
59 }
60
Jorim Jaggi5cf17872014-03-26 18:31:48 +010061 public void hide() {
Jim Miller31921482013-11-06 20:43:55 -080062 if (mShowing) {
63 if (DEBUG) Slog.v(TAG, "hide");
64 mMediaRouter.removeCallback(mMediaRouterCallback);
65 updateDisplays(false);
66 }
67 mShowing = false;
68 }
69
70 private final MediaRouter.SimpleCallback mMediaRouterCallback =
71 new MediaRouter.SimpleCallback() {
72 @Override
73 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
74 if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
75 updateDisplays(mShowing);
76 }
77
78 @Override
79 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
80 if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
81 updateDisplays(mShowing);
82 }
83
84 @Override
85 public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
86 if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
87 updateDisplays(mShowing);
88 }
89 };
90
91 private OnDismissListener mOnDismissListener = new OnDismissListener() {
92
93 @Override
94 public void onDismiss(DialogInterface dialog) {
95 mPresentation = null;
96 }
97 };
98
99 protected void updateDisplays(boolean showing) {
David Stevens53a39ea2017-08-23 18:41:49 -0700100 Presentation originalPresentation = mPresentation;
Jim Miller31921482013-11-06 20:43:55 -0800101 if (showing) {
102 MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
103 MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
104 boolean useDisplay = route != null
105 && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
106 Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null;
107
108 if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
109 if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay());
110 mPresentation.dismiss();
111 mPresentation = null;
112 }
113
114 if (mPresentation == null && presentationDisplay != null) {
115 if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay);
Jim Millerc90d6452015-07-06 18:17:34 -0700116 mPresentation = new KeyguardPresentation(mContext, presentationDisplay,
117 R.style.keyguard_presentation_theme);
Jim Miller31921482013-11-06 20:43:55 -0800118 mPresentation.setOnDismissListener(mOnDismissListener);
119 try {
120 mPresentation.show();
121 } catch (WindowManager.InvalidDisplayException ex) {
122 Slog.w(TAG, "Invalid display:", ex);
123 mPresentation = null;
124 }
125 }
126 } else {
127 if (mPresentation != null) {
128 mPresentation.dismiss();
129 mPresentation = null;
130 }
131 }
David Stevens53a39ea2017-08-23 18:41:49 -0700132
133 // mPresentation is only updated when the display changes
134 if (mPresentation != originalPresentation) {
135 final int displayId = mPresentation != null
136 ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
137 mCallback.onSecondaryDisplayShowingChanged(displayId);
138 }
Jim Miller31921482013-11-06 20:43:55 -0800139 }
140
141 private final static class KeyguardPresentation extends Presentation {
142 private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
143 private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
144 private View mClock;
145 private int mUsableWidth;
146 private int mUsableHeight;
147 private int mMarginTop;
148 private int mMarginLeft;
149 Runnable mMoveTextRunnable = new Runnable() {
150 @Override
151 public void run() {
152 int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth()));
153 int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight()));
154 mClock.setTranslationX(x);
155 mClock.setTranslationY(y);
156 mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT);
157 }
158 };
159
Jim Millerc90d6452015-07-06 18:17:34 -0700160 public KeyguardPresentation(Context context, Display display, int theme) {
161 super(context, display, theme);
Jim Miller31921482013-11-06 20:43:55 -0800162 getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
163 }
164
Jim Millerc90d6452015-07-06 18:17:34 -0700165 @Override
Jim Miller31921482013-11-06 20:43:55 -0800166 public void onDetachedFromWindow() {
167 mClock.removeCallbacks(mMoveTextRunnable);
168 }
169
170 @Override
171 protected void onCreate(Bundle savedInstanceState) {
172 super.onCreate(savedInstanceState);
173
174 Point p = new Point();
175 getDisplay().getSize(p);
176 mUsableWidth = VIDEO_SAFE_REGION * p.x/100;
177 mUsableHeight = VIDEO_SAFE_REGION * p.y/100;
178 mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200;
179 mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200;
180
181 setContentView(R.layout.keyguard_presentation);
182 mClock = findViewById(R.id.clock);
183
184 // Avoid screen burn in
185 mClock.post(mMoveTextRunnable);
186 }
187 }
188}