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.Process; 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.layoutParamsFlags = 0; 74 mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS; 75 mWindowHandle.visible = true; 76 mWindowHandle.focusable = false; 77 mWindowHandle.hasWallpaper = false; 78 mWindowHandle.paused = false; 79 mWindowHandle.ownerPid = Process.myPid(); 80 mWindowHandle.ownerUid = Process.myUid(); 81 mWindowHandle.inputFeatures = 0; 82 mWindowHandle.scaleFactor = 1.0f; 83 mWindowHandle.trustedOverlay = true; 84 85 mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId).getSession()) 86 .setContainerLayer() 87 .setName("Input Consumer " + name) 88 .setCallsite("InputConsumerImpl") 89 .build(); 90 } 91 linkToDeathRecipient()92 void linkToDeathRecipient() { 93 if (mToken == null) { 94 return; 95 } 96 97 try { 98 mToken.linkToDeath(this, 0); 99 } catch (RemoteException e) { 100 // Client died, do nothing 101 } 102 } 103 unlinkFromDeathRecipient()104 void unlinkFromDeathRecipient() { 105 if (mToken == null) { 106 return; 107 } 108 109 mToken.unlinkToDeath(this, 0); 110 } 111 layout(SurfaceControl.Transaction t, int dw, int dh)112 void layout(SurfaceControl.Transaction t, int dw, int dh) { 113 mTmpRect.set(0, 0, dw, dh); 114 layout(t, mTmpRect); 115 } 116 layout(SurfaceControl.Transaction t, Rect r)117 void layout(SurfaceControl.Transaction t, Rect r) { 118 mTmpClipRect.set(0, 0, r.width(), r.height()); 119 120 if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) { 121 return; 122 } 123 124 t.setPosition(mInputSurface, r.left, r.top); 125 t.setWindowCrop(mInputSurface, mTmpClipRect); 126 127 mOldPosition.set(r.left, r.top); 128 mOldWindowCrop.set(mTmpClipRect); 129 } 130 hide(SurfaceControl.Transaction t)131 void hide(SurfaceControl.Transaction t) { 132 t.hide(mInputSurface); 133 } 134 show(SurfaceControl.Transaction t, WindowContainer w)135 void show(SurfaceControl.Transaction t, WindowContainer w) { 136 t.show(mInputSurface); 137 t.setInputWindowInfo(mInputSurface, mWindowHandle); 138 t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1); 139 } 140 show(SurfaceControl.Transaction t, int layer)141 void show(SurfaceControl.Transaction t, int layer) { 142 t.show(mInputSurface); 143 t.setInputWindowInfo(mInputSurface, mWindowHandle); 144 t.setLayer(mInputSurface, layer); 145 } 146 reparent(SurfaceControl.Transaction t, WindowContainer wc)147 void reparent(SurfaceControl.Transaction t, WindowContainer wc) { 148 t.reparent(mInputSurface, wc.getSurfaceControl()); 149 } 150 disposeChannelsLw(SurfaceControl.Transaction t)151 void disposeChannelsLw(SurfaceControl.Transaction t) { 152 mService.mInputManager.removeInputChannel(mClientChannel.getToken()); 153 mClientChannel.dispose(); 154 t.remove(mInputSurface); 155 unlinkFromDeathRecipient(); 156 } 157 158 @Override binderDied()159 public void binderDied() { 160 synchronized (mService.getWindowManagerLock()) { 161 // Clean up the input consumer 162 final DisplayContent dc = mService.mRoot.getDisplayContent(mWindowHandle.displayId); 163 if (dc == null) { 164 return; 165 } 166 dc.getInputMonitor().destroyInputConsumer(mName); 167 unlinkFromDeathRecipient(); 168 } 169 } 170 dump(PrintWriter pw, String name, String prefix)171 void dump(PrintWriter pw, String name, String prefix) { 172 pw.println(prefix + " name=" + name + " pid=" + mClientPid + " user=" + mClientUser); 173 } 174 } 175