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); 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, displayId); 76 mWindowHandle.name = name; 77 mWindowHandle.token = mServerChannel.getToken(); 78 mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; 79 mWindowHandle.layoutParamsFlags = 0; 80 mWindowHandle.dispatchingTimeoutNanos = 81 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 82 mWindowHandle.visible = true; 83 mWindowHandle.canReceiveKeys = false; 84 mWindowHandle.hasFocus = false; 85 mWindowHandle.hasWallpaper = false; 86 mWindowHandle.paused = false; 87 mWindowHandle.ownerPid = Process.myPid(); 88 mWindowHandle.ownerUid = Process.myUid(); 89 mWindowHandle.inputFeatures = 0; 90 mWindowHandle.scaleFactor = 1.0f; 91 92 mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId).getSession()) 93 .setContainerLayer() 94 .setName("Input Consumer " + name) 95 .setCallsite("InputConsumerImpl") 96 .build(); 97 } 98 linkToDeathRecipient()99 void linkToDeathRecipient() { 100 if (mToken == null) { 101 return; 102 } 103 104 try { 105 mToken.linkToDeath(this, 0); 106 } catch (RemoteException e) { 107 // Client died, do nothing 108 } 109 } 110 unlinkFromDeathRecipient()111 void unlinkFromDeathRecipient() { 112 if (mToken == null) { 113 return; 114 } 115 116 mToken.unlinkToDeath(this, 0); 117 } 118 layout(SurfaceControl.Transaction t, int dw, int dh)119 void layout(SurfaceControl.Transaction t, int dw, int dh) { 120 mTmpRect.set(0, 0, dw, dh); 121 layout(t, mTmpRect); 122 } 123 layout(SurfaceControl.Transaction t, Rect r)124 void layout(SurfaceControl.Transaction t, Rect r) { 125 mTmpClipRect.set(0, 0, r.width(), r.height()); 126 127 if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) { 128 return; 129 } 130 131 t.setPosition(mInputSurface, r.left, r.top); 132 t.setWindowCrop(mInputSurface, mTmpClipRect); 133 134 mOldPosition.set(r.left, r.top); 135 mOldWindowCrop.set(mTmpClipRect); 136 } 137 hide(SurfaceControl.Transaction t)138 void hide(SurfaceControl.Transaction t) { 139 t.hide(mInputSurface); 140 } 141 show(SurfaceControl.Transaction t, WindowState w)142 void show(SurfaceControl.Transaction t, WindowState w) { 143 t.show(mInputSurface); 144 t.setInputWindowInfo(mInputSurface, mWindowHandle); 145 t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1); 146 } 147 show(SurfaceControl.Transaction t, int layer)148 void show(SurfaceControl.Transaction t, int layer) { 149 t.show(mInputSurface); 150 t.setInputWindowInfo(mInputSurface, mWindowHandle); 151 t.setLayer(mInputSurface, layer); 152 } 153 reparent(SurfaceControl.Transaction t, WindowContainer wc)154 void reparent(SurfaceControl.Transaction t, WindowContainer wc) { 155 t.reparent(mInputSurface, wc.getSurfaceControl()); 156 } 157 disposeChannelsLw(SurfaceControl.Transaction t)158 void disposeChannelsLw(SurfaceControl.Transaction t) { 159 mService.mInputManager.unregisterInputChannel(mServerChannel); 160 mClientChannel.dispose(); 161 mServerChannel.dispose(); 162 t.remove(mInputSurface); 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