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