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.os.IBinder;
20 import android.os.Process;
21 import android.os.RemoteException;
22 import android.os.UserHandle;
23 import android.view.Display;
24 import android.view.InputChannel;
25 import android.view.WindowManager;
26 import com.android.server.input.InputApplicationHandle;
27 import com.android.server.input.InputWindowHandle;
28 
29 import java.io.PrintWriter;
30 
31 class InputConsumerImpl implements IBinder.DeathRecipient {
32     final WindowManagerService mService;
33     final InputChannel mServerChannel, mClientChannel;
34     final InputApplicationHandle mApplicationHandle;
35     final InputWindowHandle mWindowHandle;
36 
37     final IBinder mToken;
38     final String mName;
39     final int mClientPid;
40     final UserHandle mClientUser;
41 
InputConsumerImpl(WindowManagerService service, IBinder token, String name, InputChannel inputChannel, int clientPid, UserHandle clientUser)42     InputConsumerImpl(WindowManagerService service, IBinder token, String name,
43             InputChannel inputChannel, int clientPid, UserHandle clientUser) {
44         mService = service;
45         mToken = token;
46         mName = name;
47         mClientPid = clientPid;
48         mClientUser = clientUser;
49 
50         InputChannel[] channels = InputChannel.openInputChannelPair(name);
51         mServerChannel = channels[0];
52         if (inputChannel != null) {
53             channels[1].transferTo(inputChannel);
54             channels[1].dispose();
55             mClientChannel = inputChannel;
56         } else {
57             mClientChannel = channels[1];
58         }
59         mService.mInputManager.registerInputChannel(mServerChannel, null);
60 
61         mApplicationHandle = new InputApplicationHandle(null);
62         mApplicationHandle.name = name;
63         mApplicationHandle.dispatchingTimeoutNanos =
64                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
65 
66         mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null,
67                 Display.DEFAULT_DISPLAY);
68         mWindowHandle.name = name;
69         mWindowHandle.inputChannel = mServerChannel;
70         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
71         mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
72         mWindowHandle.layoutParamsFlags = 0;
73         mWindowHandle.dispatchingTimeoutNanos =
74                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
75         mWindowHandle.visible = true;
76         mWindowHandle.canReceiveKeys = false;
77         mWindowHandle.hasFocus = false;
78         mWindowHandle.hasWallpaper = false;
79         mWindowHandle.paused = false;
80         mWindowHandle.ownerPid = Process.myPid();
81         mWindowHandle.ownerUid = Process.myUid();
82         mWindowHandle.inputFeatures = 0;
83         mWindowHandle.scaleFactor = 1.0f;
84     }
85 
linkToDeathRecipient()86     void linkToDeathRecipient() {
87         if (mToken == null) {
88             return;
89         }
90 
91         try {
92             mToken.linkToDeath(this, 0);
93         } catch (RemoteException e) {
94             // Client died, do nothing
95         }
96     }
97 
unlinkFromDeathRecipient()98     void unlinkFromDeathRecipient() {
99         if (mToken == null) {
100             return;
101         }
102 
103         mToken.unlinkToDeath(this, 0);
104     }
105 
layout(int dw, int dh)106     void layout(int dw, int dh) {
107         mWindowHandle.touchableRegion.set(0, 0, dw, dh);
108         mWindowHandle.frameLeft = 0;
109         mWindowHandle.frameTop = 0;
110         mWindowHandle.frameRight = dw;
111         mWindowHandle.frameBottom = dh;
112     }
113 
getLayerLw(int windowType)114     private int getLayerLw(int windowType) {
115         return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
116                 * WindowManagerService.TYPE_LAYER_MULTIPLIER
117                 + WindowManagerService.TYPE_LAYER_OFFSET;
118     }
119 
disposeChannelsLw()120     void disposeChannelsLw() {
121         mService.mInputManager.unregisterInputChannel(mServerChannel);
122         mClientChannel.dispose();
123         mServerChannel.dispose();
124         unlinkFromDeathRecipient();
125     }
126 
127     @Override
binderDied()128     public void binderDied() {
129         synchronized (mService.getWindowManagerLock()) {
130             // Clean up the input consumer
131             mService.mInputMonitor.destroyInputConsumer(mName);
132             unlinkFromDeathRecipient();
133         }
134     }
135 
dump(PrintWriter pw, String name, String prefix)136     void dump(PrintWriter pw, String name, String prefix) {
137         pw.println(prefix + "  name=" + name + " pid=" + mClientPid + " user=" + mClientUser);
138     }
139 }
140