下面列出了android.view.inputmethod.InputBinding#android.view.InputChannel 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
void createInputConsumer(IBinder token, String name, InputChannel inputChannel, int clientPid,
UserHandle clientUser) {
if (mInputConsumers.containsKey(name)) {
throw new IllegalStateException("Existing input consumer found with name: " + name);
}
final InputConsumerImpl consumer = new InputConsumerImpl(mService, token, name,
inputChannel, clientPid, clientUser);
switch (name) {
case INPUT_CONSUMER_WALLPAPER:
consumer.mWindowHandle.hasWallpaper = true;
break;
case INPUT_CONSUMER_PIP:
// The touchable region of the Pip input window is cropped to the bounds of the
// stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through
consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL;
break;
}
addInputConsumer(name, consumer);
}
void onSessionCreated(IInputMethod method, IInputMethodSession session,
InputChannel channel) {
synchronized (mMethodMap) {
if (mCurMethod != null && method != null
&& mCurMethod.asBinder() == method.asBinder()) {
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
mCurClient.curSession = new SessionState(mCurClient,
method, session, channel);
InputBindResult res = attachNewInputLocked(true);
if (res.method != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
MSG_BIND_METHOD, mCurClient.client, res));
}
return;
}
}
}
// Session abandoned. Close its associated input channel.
channel.dispose();
}
@Override
public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, Rect outContentInsets, Rect outStableInsets,
InputChannel outInputChannel) {
return addToDisplay(window, seq, attrs, viewVisibility, Display.DEFAULT_DISPLAY,
new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
new DisplayCutout.ParcelableWrapper() /* cutout */, outInputChannel);
}
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
// 调用 WMS.addWindow()
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
private void createSessionInternalLocked(ITvInputService service, IBinder sessionToken,
int userId) {
UserState userState = getOrCreateUserStateLocked(userId);
SessionState sessionState = userState.sessionStateMap.get(sessionToken);
if (DEBUG) {
Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.inputId + ")");
}
InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
// Set up a callback to send the session token.
ITvInputSessionCallback callback = new SessionCallback(sessionState, channels);
// Create a session. When failed, send a null token immediately.
try {
if (sessionState.isRecordingSession) {
service.createRecordingSession(callback, sessionState.inputId);
} else {
service.createSession(channels[1], callback, sessionState.inputId);
}
} catch (RemoteException e) {
Slog.e(TAG, "error in createSession", e);
removeSessionStateLocked(sessionToken, userId);
sendSessionTokenToClientLocked(sessionState.client, sessionState.inputId, null,
null, sessionState.seq);
}
channels[1].dispose();
}
private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId,
IBinder sessionToken, InputChannel channel, int seq) {
try {
client.onSessionCreated(inputId, sessionToken, channel, seq);
} catch (RemoteException e) {
Slog.e(TAG, "error in onSessionCreated", e);
}
}
/**
* Creates an input channel that will receive all input from the input dispatcher.
* @param inputChannelName The input channel name.
* @return The input channel.
*/
public InputChannel monitorInput(String inputChannelName) {
if (inputChannelName == null) {
throw new IllegalArgumentException("inputChannelName must not be null.");
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
/**
* Registers an input channel so that it can be used as an input event target.
* @param inputChannel The input channel to register.
* @param inputWindowHandle The handle of the input window associated with the
* input channel, or null if none.
*/
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
/**
* Unregisters an input channel.
* @param inputChannel The input channel to unregister.
*/
public void unregisterInputChannel(InputChannel inputChannel) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeUnregisterInputChannel(mPtr, inputChannel);
}
void setInputChannelLocked(InputChannel channel) {
if (mCurChannel != channel) {
if (mCurSender != null) {
flushPendingEventsLocked();
mCurSender.dispose();
mCurSender = null;
}
if (mCurChannel != null) {
mCurChannel.dispose();
}
mCurChannel = channel;
}
}
public IInputMethodSessionWrapper(Context context,
InputMethodSession inputMethodSession, InputChannel channel) {
mCaller = new HandlerCaller(context, null,
this, true /*asyncHandler*/);
mInputMethodSession = inputMethodSession;
mChannel = channel;
if (channel != null) {
mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper());
}
}
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility,
int displayId, Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
if (DEBUG) {
Log.d(TAG, "--- addToDisplay, replace host pkg!");
}
// 包名要替换成宿主的,不然AppOpsService校验uid时,会因为找不到插件包对应的uid,出现校验失败
attrs.packageName = mHostPackageName;
return mTarget.addToDisplay(window, seq, attrs, viewVisibility, displayId, outContentInsets, outStableInsets,
outInputChannel);
}
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility,
int displayId, Rect outContentInsets, InputChannel outInputChannel) {
if (DEBUG) {
Log.d(TAG, "--- addToDisplay, replace host pkg!");
}
// 包名要替换成宿主的,不然AppOpsService校验uid时,会因为找不到插件包对应的uid,出现校验失败
attrs.packageName = mHostPackageName;
return mTarget.addToDisplay(window, seq, attrs, viewVisibility, displayId, outContentInsets,
outInputChannel);
}
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility,
int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
if (DEBUG) {
Log.d(TAG, "--- addToDisplay, replace host pkg!");
}
// 包名要替换成宿主的,不然AppOpsService校验uid时,会因为找不到插件包对应的uid,出现校验失败
attrs.packageName = mHostPackageName;
return mTarget.addToDisplay(window, seq, attrs, viewVisibility, displayId, outContentInsets, outStableInsets,
outOutsets, outInputChannel);
}
SessionState(ClientState _client, IInputMethod _method,
IInputMethodSession _session, InputChannel _channel) {
client = _client;
method = _method;
session = _session;
channel = _channel;
}
void requestClientSessionLocked(ClientState cs) {
if (!cs.sessionRequested) {
if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
cs.sessionRequested = true;
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
MSG_CREATE_SESSION, mCurMethod, channels[1],
new MethodCallback(this, mCurMethod, channels[0])));
}
}
public PointerEventDispatcher(InputChannel inputChannel) {
super(inputChannel, UiThread.getHandler().getLooper());
}
InputConsumerImpl(WindowManagerService service, IBinder token, String name,
InputChannel inputChannel, int clientPid, UserHandle clientUser) {
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(null);
mApplicationHandle.name = name;
mApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null,
Display.DEFAULT_DISPLAY);
mWindowHandle.name = name;
mWindowHandle.inputChannel = mServerChannel;
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;
}
public WindowPositionerEventReceiver(
InputChannel inputChannel, Looper looper, Choreographer choreographer) {
super(inputChannel, looper, choreographer);
}
/**
* @param display The Display that the window being dragged is on.
*/
void register(DisplayContent displayContent) {
final Display display = displayContent.getDisplay();
if (DEBUG_TASK_POSITIONING) {
Slog.d(TAG, "Registering task positioner");
}
if (mClientChannel != null) {
Slog.e(TAG, "Task positioner already registered");
return;
}
mDisplay = display;
mDisplay.getMetrics(mDisplayMetrics);
final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
mServerChannel = channels[0];
mClientChannel = channels[1];
mService.mInputManager.registerInputChannel(mServerChannel, null);
mInputEventReceiver = new WindowPositionerEventReceiver(
mClientChannel, mService.mAnimationHandler.getLooper(),
mService.mAnimator.getChoreographer());
mDragApplicationHandle = new InputApplicationHandle(null);
mDragApplicationHandle.name = TAG;
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
mDisplay.getDisplayId());
mDragWindowHandle.name = TAG;
mDragWindowHandle.inputChannel = mServerChannel;
mDragWindowHandle.layer = mService.getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mDragWindowHandle.visible = true;
mDragWindowHandle.canReceiveKeys = false;
mDragWindowHandle.hasFocus = true;
mDragWindowHandle.hasWallpaper = false;
mDragWindowHandle.paused = false;
mDragWindowHandle.ownerPid = Process.myPid();
mDragWindowHandle.ownerUid = Process.myUid();
mDragWindowHandle.inputFeatures = 0;
mDragWindowHandle.scaleFactor = 1.0f;
// The drag window cannot receive new touches.
mDragWindowHandle.touchableRegion.setEmpty();
// The drag window covers the entire display
mDragWindowHandle.frameLeft = 0;
mDragWindowHandle.frameTop = 0;
final Point p = new Point();
mDisplay.getRealSize(p);
mDragWindowHandle.frameRight = p.x;
mDragWindowHandle.frameBottom = p.y;
// Pause rotations before a drag.
if (DEBUG_ORIENTATION) {
Slog.d(TAG, "Pausing rotation during re-position");
}
mService.pauseRotationLocked();
mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
mDisplay.getRealSize(mMaxVisibleSize);
mDragEnded = false;
}
DragInputEventReceiver(InputChannel inputChannel, Looper looper,
DragDropController controller) {
super(inputChannel, looper);
mDragDropController = controller;
}
InputInterceptor(Display display) {
InputChannel[] channels = InputChannel.openInputChannelPair("drag");
mServerChannel = channels[0];
mClientChannel = channels[1];
mService.mInputManager.registerInputChannel(mServerChannel, null);
mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
mService.mH.getLooper(), mDragDropController);
mDragApplicationHandle = new InputApplicationHandle(null);
mDragApplicationHandle.name = "drag";
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
display.getDisplayId());
mDragWindowHandle.name = "drag";
mDragWindowHandle.inputChannel = mServerChannel;
mDragWindowHandle.layer = getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mDragWindowHandle.visible = true;
mDragWindowHandle.canReceiveKeys = false;
mDragWindowHandle.hasFocus = true;
mDragWindowHandle.hasWallpaper = false;
mDragWindowHandle.paused = false;
mDragWindowHandle.ownerPid = Process.myPid();
mDragWindowHandle.ownerUid = Process.myUid();
mDragWindowHandle.inputFeatures = 0;
mDragWindowHandle.scaleFactor = 1.0f;
// The drag window cannot receive new touches.
mDragWindowHandle.touchableRegion.setEmpty();
// The drag window covers the entire display
mDragWindowHandle.frameLeft = 0;
mDragWindowHandle.frameTop = 0;
mDragWindowHandle.frameRight = mDisplaySize.x;
mDragWindowHandle.frameBottom = mDisplaySize.y;
// Pause rotations before a drag.
if (DEBUG_ORIENTATION) {
Slog.d(TAG_WM, "Pausing rotation during drag");
}
mService.pauseRotationLocked();
}
InputChannel getInputChannel() {
return mInputInterceptor == null ? null : mInputInterceptor.mServerChannel;
}
@Override
public void accept(WindowState w) {
final InputChannel inputChannel = w.mInputChannel;
final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
if (inputChannel == null || inputWindowHandle == null || w.mRemoved
|| w.canReceiveTouchInput()) {
// Skip this window because it cannot possibly receive input.
return;
}
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
final int type = w.mAttrs.type;
final boolean hasFocus = w == mInputFocus;
final boolean isVisible = w.isVisibleLw();
if (mAddRecentsAnimationInputConsumerHandle) {
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
if (recentsAnimationController != null
&& recentsAnimationController.hasInputConsumerForApp(w.mAppToken)) {
if (recentsAnimationController.updateInputConsumerForApp(
recentsAnimationInputConsumer, hasFocus)) {
addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
mAddRecentsAnimationInputConsumerHandle = false;
}
// Skip adding the window below regardless of whether there is an input consumer
// to handle it
return;
}
}
if (w.inPinnedWindowingMode()) {
if (mAddPipInputConsumerHandle
&& (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
// Update the bounds of the Pip input consumer to match the window bounds.
w.getBounds(mTmpRect);
pipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
addInputWindowHandle(pipInputConsumer.mWindowHandle);
mAddPipInputConsumerHandle = false;
}
// TODO: Fix w.canReceiveTouchInput() to handle this case
if (!hasFocus) {
// Skip this pinned stack window if it does not have focus
return;
}
}
if (mAddInputConsumerHandle
&& inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
addInputWindowHandle(navInputConsumer.mWindowHandle);
mAddInputConsumerHandle = false;
}
if (mAddWallpaperInputConsumerHandle) {
if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
// Add the wallpaper input consumer above the first visible wallpaper.
addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
mAddWallpaperInputConsumerHandle = false;
}
}
if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
mDisableWallpaperTouchEvents = true;
}
final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
&& (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
&& !mDisableWallpaperTouchEvents;
// If there's a drag in progress and 'child' is a potential drop target,
// make sure it's been told about the drag
if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
mService.mDragDropController.sendDragStartedIfNeededLocked(w);
}
addInputWindowHandle(
inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
}
default boolean registerInputChannel(
DragState state, Display display, InputManagerService service,
InputChannel source) {
state.register(display);
return service.transferTouchFocus(source, state.getInputChannel());
}
SessionCallback(SessionState sessionState, InputChannel[] channels) {
mSessionState = sessionState;
mChannels = channels;
}
private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
InputWindowHandle inputWindowHandle, boolean monitor);
private static native boolean nativeTransferTouchFocus(long ptr,
InputChannel fromChannel, InputChannel toChannel);
public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}