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, SurfaceControl.Transaction t)53 InputConsumerImpl(WindowManagerService service, IBinder token, String name, 54 InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId, 55 SurfaceControl.Transaction t) { 56 mService = service; 57 mToken = token; 58 mName = name; 59 mClientPid = clientPid; 60 mClientUser = clientUser; 61 62 mClientChannel = mService.mInputManager.createInputChannel(name); 63 if (inputChannel != null) { 64 mClientChannel.copyTo(inputChannel); 65 } 66 67 mApplicationHandle = new InputApplicationHandle(new Binder(), name, 68 DEFAULT_DISPATCHING_TIMEOUT_MILLIS); 69 70 mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId); 71 mWindowHandle.name = name; 72 mWindowHandle.token = mClientChannel.getToken(); 73 mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; 74 mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 75 mWindowHandle.ownerPid = WindowManagerService.MY_PID; 76 mWindowHandle.ownerUid = WindowManagerService.MY_UID; 77 mWindowHandle.scaleFactor = 1.0f; 78 mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE; 79 80 mInputSurface = mService.makeSurfaceBuilder( 81 mService.mRoot.getDisplayContent(displayId).getSession()) 82 .setContainerLayer() 83 .setName("Input Consumer " + name) 84 .setCallsite("InputConsumerImpl") 85 .build(); 86 mWindowHandle.setTrustedOverlay(t, mInputSurface, true); 87 } 88 linkToDeathRecipient()89 void linkToDeathRecipient() { 90 if (mToken == null) { 91 return; 92 } 93 94 try { 95 mToken.linkToDeath(this, 0); 96 } catch (RemoteException e) { 97 // Client died, do nothing 98 } 99 } 100 unlinkFromDeathRecipient()101 void unlinkFromDeathRecipient() { 102 if (mToken == null) { 103 return; 104 } 105 106 mToken.unlinkToDeath(this, 0); 107 } 108 layout(SurfaceControl.Transaction t, int dw, int dh)109 void layout(SurfaceControl.Transaction t, int dw, int dh) { 110 mTmpRect.set(0, 0, dw, dh); 111 layout(t, mTmpRect); 112 } 113 layout(SurfaceControl.Transaction t, Rect r)114 void layout(SurfaceControl.Transaction t, Rect r) { 115 mTmpClipRect.set(0, 0, r.width(), r.height()); 116 117 if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) { 118 return; 119 } 120 121 t.setPosition(mInputSurface, r.left, r.top); 122 t.setWindowCrop(mInputSurface, mTmpClipRect); 123 124 mOldPosition.set(r.left, r.top); 125 mOldWindowCrop.set(mTmpClipRect); 126 } 127 hide(SurfaceControl.Transaction t)128 void hide(SurfaceControl.Transaction t) { 129 t.hide(mInputSurface); 130 } 131 show(SurfaceControl.Transaction t, WindowContainer w)132 void show(SurfaceControl.Transaction t, WindowContainer w) { 133 t.show(mInputSurface); 134 t.setInputWindowInfo(mInputSurface, mWindowHandle); 135 t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1 + w.getChildCount()); 136 } 137 show(SurfaceControl.Transaction t, int layer)138 void show(SurfaceControl.Transaction t, int layer) { 139 t.show(mInputSurface); 140 t.setInputWindowInfo(mInputSurface, mWindowHandle); 141 t.setLayer(mInputSurface, layer); 142 } 143 reparent(SurfaceControl.Transaction t, WindowContainer wc)144 void reparent(SurfaceControl.Transaction t, WindowContainer wc) { 145 t.reparent(mInputSurface, wc.getSurfaceControl()); 146 } 147 disposeChannelsLw(SurfaceControl.Transaction t)148 void disposeChannelsLw(SurfaceControl.Transaction t) { 149 mService.mInputManager.removeInputChannel(mClientChannel.getToken()); 150 mClientChannel.dispose(); 151 t.remove(mInputSurface); 152 unlinkFromDeathRecipient(); 153 } 154 155 @Override binderDied()156 public void binderDied() { 157 synchronized (mService.getWindowManagerLock()) { 158 // Clean up the input consumer 159 final DisplayContent dc = mService.mRoot.getDisplayContent(mWindowHandle.displayId); 160 if (dc == null) { 161 return; 162 } 163 dc.getInputMonitor().destroyInputConsumer(mToken); 164 unlinkFromDeathRecipient(); 165 } 166 } 167 dump(PrintWriter pw, String name, String prefix)168 void dump(PrintWriter pw, String name, String prefix) { 169 pw.println(prefix + " name=" + name + " pid=" + mClientPid + " user=" + mClientUser); 170 } 171 } 172