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