blob: db4f988a9122ee97b43c8b8509285a0d4910f4b7 [file] [log] [blame]
Winson Chungd2d90972017-02-28 11:40:41 -08001/*
2 * Copyright (C) 2017 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
17package com.android.systemui.pip.phone;
18
19import static android.view.WindowManager.INPUT_CONSUMER_PIP;
20
Winson Chung6463c362017-09-25 16:23:26 -070021import android.os.Binder;
22import android.os.IBinder;
Winson Chungd2d90972017-02-28 11:40:41 -080023import android.os.Looper;
24import android.os.RemoteException;
25import android.util.Log;
Winson Chung4a526c12017-05-16 13:35:43 -070026import android.view.BatchedInputEventReceiver;
27import android.view.Choreographer;
Winson Chungd2d90972017-02-28 11:40:41 -080028import android.view.InputChannel;
29import android.view.InputEvent;
Winson Chungd2d90972017-02-28 11:40:41 -080030import android.view.IWindowManager;
31import android.view.MotionEvent;
32
33import java.io.PrintWriter;
34
35/**
36 * Manages the input consumer that allows the SystemUI to control the PiP.
37 */
38public class InputConsumerController {
39
40 private static final String TAG = InputConsumerController.class.getSimpleName();
41
42 /**
43 * Listener interface for callers to subscribe to touch events.
44 */
45 public interface TouchListener {
46 boolean onTouchEvent(MotionEvent ev);
47 }
48
49 /**
Phil Weaverf00cd142017-03-03 13:44:00 -080050 * Listener interface for callers to learn when this class is registered or unregistered with
51 * window manager
52 */
53 public interface RegistrationListener {
54 void onRegistrationChanged(boolean isRegistered);
55 }
56
57 /**
Winson Chung4a526c12017-05-16 13:35:43 -070058 * Input handler used for the PiP input consumer. Input events are batched and consumed with the
59 * SurfaceFlinger vsync.
Winson Chungd2d90972017-02-28 11:40:41 -080060 */
Winson Chung4a526c12017-05-16 13:35:43 -070061 private final class PipInputEventReceiver extends BatchedInputEventReceiver {
Winson Chungd2d90972017-02-28 11:40:41 -080062
63 public PipInputEventReceiver(InputChannel inputChannel, Looper looper) {
Winson Chung4a526c12017-05-16 13:35:43 -070064 super(inputChannel, looper, Choreographer.getSfInstance());
Winson Chungd2d90972017-02-28 11:40:41 -080065 }
66
67 @Override
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070068 public void onInputEvent(InputEvent event, int displayId) {
Winson Chungd2d90972017-02-28 11:40:41 -080069 boolean handled = true;
70 try {
71 // To be implemented for input handling over Pip windows
72 if (mListener != null && event instanceof MotionEvent) {
73 MotionEvent ev = (MotionEvent) event;
74 handled = mListener.onTouchEvent(ev);
75 }
76 } finally {
77 finishInputEvent(event, handled);
78 }
79 }
80 }
81
Winson Chung6463c362017-09-25 16:23:26 -070082 private final IWindowManager mWindowManager;
83 private final IBinder mToken;
Winson Chungd2d90972017-02-28 11:40:41 -080084
85 private PipInputEventReceiver mInputEventReceiver;
86 private TouchListener mListener;
Phil Weaverf00cd142017-03-03 13:44:00 -080087 private RegistrationListener mRegistrationListener;
Winson Chungd2d90972017-02-28 11:40:41 -080088
89 public InputConsumerController(IWindowManager windowManager) {
90 mWindowManager = windowManager;
Winson Chung6463c362017-09-25 16:23:26 -070091 mToken = new Binder();
Winson Chungd2d90972017-02-28 11:40:41 -080092 registerInputConsumer();
93 }
94
95 /**
96 * Sets the touch listener.
97 */
98 public void setTouchListener(TouchListener listener) {
99 mListener = listener;
100 }
101
102 /**
Phil Weaverf00cd142017-03-03 13:44:00 -0800103 * Sets the registration listener.
104 */
105 public void setRegistrationListener(RegistrationListener listener) {
106 mRegistrationListener = listener;
Winson Chungfe1fa642017-03-13 10:51:22 -0700107 if (mRegistrationListener != null) {
108 mRegistrationListener.onRegistrationChanged(mInputEventReceiver != null);
109 }
Phil Weaverf00cd142017-03-03 13:44:00 -0800110 }
111
112 /**
113 * Check if the InputConsumer is currently registered with WindowManager
114 *
115 * @return {@code true} if registered, {@code false} if not.
116 */
117 public boolean isRegistered() {
118 return mInputEventReceiver != null;
119 }
120
121 /**
Winson Chungd2d90972017-02-28 11:40:41 -0800122 * Registers the input consumer.
123 */
124 public void registerInputConsumer() {
125 if (mInputEventReceiver == null) {
126 final InputChannel inputChannel = new InputChannel();
127 try {
128 mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
Winson Chung6463c362017-09-25 16:23:26 -0700129 mWindowManager.createInputConsumer(mToken, INPUT_CONSUMER_PIP, inputChannel);
Winson Chungd2d90972017-02-28 11:40:41 -0800130 } catch (RemoteException e) {
131 Log.e(TAG, "Failed to create PIP input consumer", e);
132 }
133 mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper());
Winson Chungfe1fa642017-03-13 10:51:22 -0700134 if (mRegistrationListener != null) {
135 mRegistrationListener.onRegistrationChanged(true /* isRegistered */);
136 }
Winson Chungd2d90972017-02-28 11:40:41 -0800137 }
138 }
139
140 /**
141 * Unregisters the input consumer.
142 */
143 public void unregisterInputConsumer() {
144 if (mInputEventReceiver != null) {
145 try {
146 mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP);
147 } catch (RemoteException e) {
148 Log.e(TAG, "Failed to destroy PIP input consumer", e);
149 }
150 mInputEventReceiver.dispose();
151 mInputEventReceiver = null;
Winson Chungfe1fa642017-03-13 10:51:22 -0700152 if (mRegistrationListener != null) {
153 mRegistrationListener.onRegistrationChanged(false /* isRegistered */);
154 }
Winson Chungd2d90972017-02-28 11:40:41 -0800155 }
156 }
157
158 public void dump(PrintWriter pw, String prefix) {
159 final String innerPrefix = prefix + " ";
160 pw.println(prefix + TAG);
161 pw.println(innerPrefix + "registered=" + (mInputEventReceiver != null));
162 }
163}