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