1 /*
2  * Copyright (C) 2011 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 
17 package com.android.server.wm;
18 
19 import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
20 
21 import android.graphics.Point;
22 import android.graphics.Rect;
23 import android.os.Binder;
24 import android.os.IBinder;
25 import android.os.InputConfig;
26 import android.os.RemoteException;
27 import android.os.UserHandle;
28 import android.view.InputApplicationHandle;
29 import android.view.InputChannel;
30 import android.view.InputWindowHandle;
31 import android.view.SurfaceControl;
32 import android.view.WindowManager;
33 
34 import java.io.PrintWriter;
35 
36 class InputConsumerImpl implements IBinder.DeathRecipient {
37     final WindowManagerService mService;
38     final InputChannel mClientChannel;
39     final InputApplicationHandle mApplicationHandle;
40     final InputWindowHandle mWindowHandle;
41 
42     final IBinder mToken;
43     final String mName;
44     final int mClientPid;
45     final UserHandle mClientUser;
46 
47     final SurfaceControl mInputSurface;
48     Rect mTmpClipRect = new Rect();
49     private final Rect mTmpRect = new Rect();
50     private final Point mOldPosition = new Point();
51     private final Rect mOldWindowCrop = new Rect();
52 
InputConsumerImpl(WindowManagerService service, IBinder token, String name, InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId, SurfaceControl.Transaction t)53     InputConsumerImpl(WindowManagerService service, IBinder token, String name,
54             InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId,
55             SurfaceControl.Transaction t) {
56         mService = service;
57         mToken = token;
58         mName = name;
59         mClientPid = clientPid;
60         mClientUser = clientUser;
61 
62         mClientChannel = mService.mInputManager.createInputChannel(name);
63         if (inputChannel != null) {
64             mClientChannel.copyTo(inputChannel);
65         }
66 
67         mApplicationHandle = new InputApplicationHandle(new Binder(), name,
68                 DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
69 
70         mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
71         mWindowHandle.name = name;
72         mWindowHandle.token = mClientChannel.getToken();
73         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
74         mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
75         mWindowHandle.ownerPid = WindowManagerService.MY_PID;
76         mWindowHandle.ownerUid = WindowManagerService.MY_UID;
77         mWindowHandle.scaleFactor = 1.0f;
78         mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
79 
80         mInputSurface = mService.makeSurfaceBuilder(
81                         mService.mRoot.getDisplayContent(displayId).getSession())
82                 .setContainerLayer()
83                 .setName("Input Consumer " + name)
84                 .setCallsite("InputConsumerImpl")
85                 .build();
86         mWindowHandle.setTrustedOverlay(t, mInputSurface, true);
87     }
88 
linkToDeathRecipient()89     void linkToDeathRecipient() {
90         if (mToken == null) {
91             return;
92         }
93 
94         try {
95             mToken.linkToDeath(this, 0);
96         } catch (RemoteException e) {
97             // Client died, do nothing
98         }
99     }
100 
unlinkFromDeathRecipient()101     void unlinkFromDeathRecipient() {
102         if (mToken == null) {
103             return;
104         }
105 
106         mToken.unlinkToDeath(this, 0);
107     }
108 
layout(SurfaceControl.Transaction t, int dw, int dh)109     void layout(SurfaceControl.Transaction t, int dw, int dh) {
110         mTmpRect.set(0, 0, dw, dh);
111         layout(t, mTmpRect);
112     }
113 
layout(SurfaceControl.Transaction t, Rect r)114     void layout(SurfaceControl.Transaction t, Rect r) {
115         mTmpClipRect.set(0, 0, r.width(), r.height());
116 
117         if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) {
118             return;
119         }
120 
121         t.setPosition(mInputSurface, r.left, r.top);
122         t.setWindowCrop(mInputSurface, mTmpClipRect);
123 
124         mOldPosition.set(r.left, r.top);
125         mOldWindowCrop.set(mTmpClipRect);
126     }
127 
hide(SurfaceControl.Transaction t)128     void hide(SurfaceControl.Transaction t) {
129         t.hide(mInputSurface);
130     }
131 
show(SurfaceControl.Transaction t, WindowContainer w)132     void show(SurfaceControl.Transaction t, WindowContainer w) {
133         t.show(mInputSurface);
134         t.setInputWindowInfo(mInputSurface, mWindowHandle);
135         t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1 + w.getChildCount());
136     }
137 
show(SurfaceControl.Transaction t, int layer)138     void show(SurfaceControl.Transaction t, int layer) {
139         t.show(mInputSurface);
140         t.setInputWindowInfo(mInputSurface, mWindowHandle);
141         t.setLayer(mInputSurface, layer);
142     }
143 
reparent(SurfaceControl.Transaction t, WindowContainer wc)144     void reparent(SurfaceControl.Transaction t, WindowContainer wc) {
145         t.reparent(mInputSurface, wc.getSurfaceControl());
146     }
147 
disposeChannelsLw(SurfaceControl.Transaction t)148     void disposeChannelsLw(SurfaceControl.Transaction t) {
149         mService.mInputManager.removeInputChannel(mClientChannel.getToken());
150         mClientChannel.dispose();
151         t.remove(mInputSurface);
152         unlinkFromDeathRecipient();
153     }
154 
155     @Override
binderDied()156     public void binderDied() {
157         synchronized (mService.getWindowManagerLock()) {
158             // Clean up the input consumer
159             final DisplayContent dc = mService.mRoot.getDisplayContent(mWindowHandle.displayId);
160             if (dc == null) {
161                 return;
162             }
163             dc.getInputMonitor().destroyInputConsumer(mToken);
164             unlinkFromDeathRecipient();
165         }
166     }
167 
dump(PrintWriter pw, String name, String prefix)168     void dump(PrintWriter pw, String name, String prefix) {
169         pw.println(prefix + "  name=" + name + " pid=" + mClientPid + " user=" + mClientUser);
170     }
171 }
172