| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wm; |
| |
| import android.graphics.Point; |
| import android.graphics.Rect; |
| import android.os.Binder; |
| import android.os.IBinder; |
| import android.os.Process; |
| import android.os.RemoteException; |
| import android.os.UserHandle; |
| import android.view.InputApplicationHandle; |
| import android.view.InputChannel; |
| import android.view.InputWindowHandle; |
| import android.view.SurfaceControl; |
| import android.view.WindowManager; |
| |
| import java.io.PrintWriter; |
| |
| class InputConsumerImpl implements IBinder.DeathRecipient { |
| final WindowManagerService mService; |
| final InputChannel mServerChannel, mClientChannel; |
| final InputApplicationHandle mApplicationHandle; |
| final InputWindowHandle mWindowHandle; |
| |
| final IBinder mToken; |
| final String mName; |
| final int mClientPid; |
| final UserHandle mClientUser; |
| |
| final SurfaceControl mInputSurface; |
| Rect mTmpClipRect = new Rect(); |
| private final Rect mTmpRect = new Rect(); |
| private final Point mOldPosition = new Point(); |
| private final Rect mOldWindowCrop = new Rect(); |
| |
| InputConsumerImpl(WindowManagerService service, IBinder token, String name, |
| InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) { |
| mService = service; |
| mToken = token; |
| mName = name; |
| mClientPid = clientPid; |
| mClientUser = clientUser; |
| |
| InputChannel[] channels = InputChannel.openInputChannelPair(name); |
| mServerChannel = channels[0]; |
| if (inputChannel != null) { |
| channels[1].transferTo(inputChannel); |
| channels[1].dispose(); |
| mClientChannel = inputChannel; |
| } else { |
| mClientChannel = channels[1]; |
| } |
| mService.mInputManager.registerInputChannel(mServerChannel, null); |
| |
| mApplicationHandle = new InputApplicationHandle(new Binder()); |
| mApplicationHandle.name = name; |
| mApplicationHandle.dispatchingTimeoutNanos = |
| WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; |
| |
| mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId); |
| mWindowHandle.name = name; |
| mWindowHandle.token = mServerChannel.getToken(); |
| mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; |
| mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType); |
| mWindowHandle.layoutParamsFlags = 0; |
| mWindowHandle.dispatchingTimeoutNanos = |
| WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; |
| mWindowHandle.visible = true; |
| mWindowHandle.canReceiveKeys = false; |
| mWindowHandle.hasFocus = false; |
| mWindowHandle.hasWallpaper = false; |
| mWindowHandle.paused = false; |
| mWindowHandle.ownerPid = Process.myPid(); |
| mWindowHandle.ownerUid = Process.myUid(); |
| mWindowHandle.inputFeatures = 0; |
| mWindowHandle.scaleFactor = 1.0f; |
| |
| mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId) |
| .getSession()).setContainerLayer().setName("Input Consumer " + name) |
| .build(); |
| } |
| |
| void linkToDeathRecipient() { |
| if (mToken == null) { |
| return; |
| } |
| |
| try { |
| mToken.linkToDeath(this, 0); |
| } catch (RemoteException e) { |
| // Client died, do nothing |
| } |
| } |
| |
| void unlinkFromDeathRecipient() { |
| if (mToken == null) { |
| return; |
| } |
| |
| mToken.unlinkToDeath(this, 0); |
| } |
| |
| void layout(SurfaceControl.Transaction t, int dw, int dh) { |
| mTmpRect.set(0, 0, dw, dh); |
| layout(t, mTmpRect); |
| } |
| |
| void layout(SurfaceControl.Transaction t, Rect r) { |
| mTmpClipRect.set(0, 0, r.width(), r.height()); |
| |
| if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) { |
| return; |
| } |
| |
| t.setPosition(mInputSurface, r.left, r.top); |
| t.setWindowCrop(mInputSurface, mTmpClipRect); |
| |
| mOldPosition.set(r.left, r.top); |
| mOldWindowCrop.set(mTmpClipRect); |
| } |
| |
| void hide(SurfaceControl.Transaction t) { |
| t.hide(mInputSurface); |
| } |
| |
| void show(SurfaceControl.Transaction t, WindowState w) { |
| t.show(mInputSurface); |
| t.setInputWindowInfo(mInputSurface, mWindowHandle); |
| t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1); |
| } |
| |
| void show(SurfaceControl.Transaction t, int layer) { |
| t.show(mInputSurface); |
| t.setInputWindowInfo(mInputSurface, mWindowHandle); |
| t.setLayer(mInputSurface, layer); |
| } |
| |
| private int getLayerLw(int windowType) { |
| return mService.mPolicy.getWindowLayerFromTypeLw(windowType) |
| * WindowManagerService.TYPE_LAYER_MULTIPLIER |
| + WindowManagerService.TYPE_LAYER_OFFSET; |
| } |
| |
| void disposeChannelsLw() { |
| mService.mInputManager.unregisterInputChannel(mServerChannel); |
| mClientChannel.dispose(); |
| mServerChannel.dispose(); |
| unlinkFromDeathRecipient(); |
| } |
| |
| @Override |
| public void binderDied() { |
| synchronized (mService.getWindowManagerLock()) { |
| // Clean up the input consumer |
| final InputMonitor inputMonitor = |
| mService.mRoot.getDisplayContent(mWindowHandle.displayId).getInputMonitor(); |
| inputMonitor.destroyInputConsumer(mName); |
| unlinkFromDeathRecipient(); |
| } |
| } |
| |
| void dump(PrintWriter pw, String name, String prefix) { |
| pw.println(prefix + " name=" + name + " pid=" + mClientPid + " user=" + mClientUser); |
| } |
| } |