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