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.Process;
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.layoutParamsFlags = 0;
74         mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
75         mWindowHandle.visible = true;
76         mWindowHandle.focusable = false;
77         mWindowHandle.hasWallpaper = false;
78         mWindowHandle.paused = false;
79         mWindowHandle.ownerPid = Process.myPid();
80         mWindowHandle.ownerUid = Process.myUid();
81         mWindowHandle.inputFeatures = 0;
82         mWindowHandle.scaleFactor = 1.0f;
83         mWindowHandle.trustedOverlay = true;
84 
85         mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId).getSession())
86                 .setContainerLayer()
87                 .setName("Input Consumer " + name)
88                 .setCallsite("InputConsumerImpl")
89                 .build();
90     }
91 
linkToDeathRecipient()92     void linkToDeathRecipient() {
93         if (mToken == null) {
94             return;
95         }
96 
97         try {
98             mToken.linkToDeath(this, 0);
99         } catch (RemoteException e) {
100             // Client died, do nothing
101         }
102     }
103 
unlinkFromDeathRecipient()104     void unlinkFromDeathRecipient() {
105         if (mToken == null) {
106             return;
107         }
108 
109         mToken.unlinkToDeath(this, 0);
110     }
111 
layout(SurfaceControl.Transaction t, int dw, int dh)112     void layout(SurfaceControl.Transaction t, int dw, int dh) {
113         mTmpRect.set(0, 0, dw, dh);
114         layout(t, mTmpRect);
115     }
116 
layout(SurfaceControl.Transaction t, Rect r)117     void layout(SurfaceControl.Transaction t, Rect r) {
118         mTmpClipRect.set(0, 0, r.width(), r.height());
119 
120         if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) {
121             return;
122         }
123 
124         t.setPosition(mInputSurface, r.left, r.top);
125         t.setWindowCrop(mInputSurface, mTmpClipRect);
126 
127         mOldPosition.set(r.left, r.top);
128         mOldWindowCrop.set(mTmpClipRect);
129     }
130 
hide(SurfaceControl.Transaction t)131     void hide(SurfaceControl.Transaction t) {
132         t.hide(mInputSurface);
133     }
134 
show(SurfaceControl.Transaction t, WindowContainer w)135     void show(SurfaceControl.Transaction t, WindowContainer w) {
136         t.show(mInputSurface);
137         t.setInputWindowInfo(mInputSurface, mWindowHandle);
138         t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1);
139     }
140 
show(SurfaceControl.Transaction t, int layer)141     void show(SurfaceControl.Transaction t, int layer) {
142         t.show(mInputSurface);
143         t.setInputWindowInfo(mInputSurface, mWindowHandle);
144         t.setLayer(mInputSurface, layer);
145     }
146 
reparent(SurfaceControl.Transaction t, WindowContainer wc)147     void reparent(SurfaceControl.Transaction t, WindowContainer wc) {
148         t.reparent(mInputSurface, wc.getSurfaceControl());
149     }
150 
disposeChannelsLw(SurfaceControl.Transaction t)151     void disposeChannelsLw(SurfaceControl.Transaction t) {
152         mService.mInputManager.removeInputChannel(mClientChannel.getToken());
153         mClientChannel.dispose();
154         t.remove(mInputSurface);
155         unlinkFromDeathRecipient();
156     }
157 
158     @Override
binderDied()159     public void binderDied() {
160         synchronized (mService.getWindowManagerLock()) {
161             // Clean up the input consumer
162             final DisplayContent dc = mService.mRoot.getDisplayContent(mWindowHandle.displayId);
163             if (dc == null) {
164                 return;
165             }
166             dc.getInputMonitor().destroyInputConsumer(mName);
167             unlinkFromDeathRecipient();
168         }
169     }
170 
dump(PrintWriter pw, String name, String prefix)171     void dump(PrintWriter pw, String name, String prefix) {
172         pw.println(prefix + "  name=" + name + " pid=" + mClientPid + " user=" + mClientUser);
173     }
174 }
175