blob: 8dae0163b612d451c1050eb54c082fa3ed0c59ad [file] [log] [blame]
/*
* 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);
}
}