/*
 * Copyright (C) 2018 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.inputmethod;

import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.AnyThread;
import android.annotation.BinderThread;
import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.InputChannel;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSystemProperty;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IMultiClientInputMethod;
import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.IMultiClientInputMethodSession;
import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason;
import com.android.internal.inputmethod.UnbindReason;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.WindowManagerInternal;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.util.Collections;
import java.util.List;
import java.util.WeakHashMap;

/**
 * Actual implementation of multi-client InputMethodManagerService.
 *
 * <p>This system service is intentionally compatible with {@link InputMethodManagerService} so that
 * we can switch the implementation at the boot time.</p>
 */
public final class MultiClientInputMethodManagerService {
    private static final String TAG = "MultiClientInputMethodManagerService";
    private static final boolean DEBUG = false;

    private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE =
            "config_perDisplayFocusEnabled is not true.";

    private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG =
            "Consider rebuilding the system image after enabling config_perDisplayFocusEnabled to "
                    + "make IME focus compatible with multi-client IME mode.";

    private static final long RECONNECT_DELAY_MSEC = 1000;

    /**
     * Unlike {@link InputMethodManagerService}, {@link MultiClientInputMethodManagerService}
     * always binds to the IME with {@link Context#BIND_FOREGROUND_SERVICE} for now for simplicity.
     */
    private static final int IME_CONNECTION_UNIFIED_BIND_FLAGS =
            Context.BIND_AUTO_CREATE
                    | Context.BIND_NOT_VISIBLE
                    | Context.BIND_NOT_FOREGROUND
                    | Context.BIND_FOREGROUND_SERVICE;

    private static final ComponentName sImeComponentName =
            InputMethodSystemProperty.sMultiClientImeComponentName;

    private static void reportNotSupported() {
        if (DEBUG) {
            Slog.d(TAG, "non-supported operation. callers=" + Debug.getCallers(3));
        }
    }

    /**
     * {@link MultiClientInputMethodManagerService} is not intended to be instantiated.
     */
    private MultiClientInputMethodManagerService() {
    }

    /**
     * The implementation of {@link SystemService} for multi-client IME.
     */
    public static final class Lifecycle extends SystemService {
        private final ApiCallbacks mApiCallbacks;
        private final OnWorkerThreadCallback mOnWorkerThreadCallback;

        @MainThread
        public Lifecycle(Context context) {
            super(context);

            final UserToInputMethodInfoMap userIdToInputMethodInfoMapper =
                    new UserToInputMethodInfoMap();
            final UserDataMap userDataMap = new UserDataMap();
            final HandlerThread workerThread = new HandlerThread(TAG);
            workerThread.start();
            mApiCallbacks = new ApiCallbacks(context, userDataMap, userIdToInputMethodInfoMapper);
            mOnWorkerThreadCallback = new OnWorkerThreadCallback(
                    context, userDataMap, userIdToInputMethodInfoMapper,
                    new Handler(workerThread.getLooper(), msg -> false, true));

            LocalServices.addService(InputMethodManagerInternal.class,
                    new InputMethodManagerInternal() {
                        @Override
                        public void setInteractive(boolean interactive) {
                            reportNotSupported();
                        }

                        @Override
                        public void hideCurrentInputMethod() {
                            reportNotSupported();
                        }

                        @Override
                        public List<InputMethodInfo> getInputMethodListAsUser(
                                @UserIdInt int userId) {
                            return userIdToInputMethodInfoMapper.getAsList(userId);
                        }

                        @Override
                        public List<InputMethodInfo> getEnabledInputMethodListAsUser(
                                @UserIdInt int userId) {
                            return userIdToInputMethodInfoMapper.getAsList(userId);
                        }
                    });
        }

        @MainThread
        @Override
        public void onBootPhase(int phase) {
            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
                    OnWorkerThreadCallback::onBootPhase, mOnWorkerThreadCallback, phase));
        }

        @MainThread
        @Override
        public void onStart() {
            publishBinderService(Context.INPUT_METHOD_SERVICE, mApiCallbacks);
        }

        @MainThread
        @Override
        public void onStartUser(@UserIdInt int userId) {
            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
                    OnWorkerThreadCallback::onStartUser, mOnWorkerThreadCallback, userId));
        }

        @MainThread
        @Override
        public void onUnlockUser(@UserIdInt int userId) {
            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
                    OnWorkerThreadCallback::onUnlockUser, mOnWorkerThreadCallback, userId));
        }

        @MainThread
        @Override
        public void onStopUser(@UserIdInt int userId) {
            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
                    OnWorkerThreadCallback::onStopUser, mOnWorkerThreadCallback, userId));
        }
    }

    private static final class OnWorkerThreadCallback {
        private final Context mContext;
        private final UserDataMap mUserDataMap;
        private final UserToInputMethodInfoMap mInputMethodInfoMap;
        private final Handler mHandler;

        OnWorkerThreadCallback(Context context, UserDataMap userDataMap,
                UserToInputMethodInfoMap inputMethodInfoMap, Handler handler) {
            mContext = context;
            mUserDataMap = userDataMap;
            mInputMethodInfoMap = inputMethodInfoMap;
            mHandler = handler;
        }

        @AnyThread
        Handler getHandler() {
            return mHandler;
        }

        @WorkerThread
        private void tryBindInputMethodService(@UserIdInt int userId) {
            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.i(TAG, "tryBindInputMethodService is called for an unknown user=" + userId);
                return;
            }

            final InputMethodInfo imi = queryInputMethod(mContext, userId, sImeComponentName);
            if (imi == null) {
                Slog.w(TAG, "Multi-client InputMethod is not found. component="
                        + sImeComponentName);
                synchronized (data.mLock) {
                    switch (data.mState) {
                        case PerUserState.USER_LOCKED:
                        case PerUserState.SERVICE_NOT_QUERIED:
                        case PerUserState.SERVICE_RECOGNIZED:
                        case PerUserState.UNBIND_CALLED:
                            // Safe to clean up.
                            mInputMethodInfoMap.remove(userId);
                            break;
                    }
                }
                return;
            }

            synchronized (data.mLock) {
                switch (data.mState) {
                    case PerUserState.USER_LOCKED:
                        // If the user is still locked, we currently do not try to start IME.
                        return;
                    case PerUserState.SERVICE_NOT_QUERIED:
                    case PerUserState.SERVICE_RECOGNIZED:
                    case PerUserState.UNBIND_CALLED:
                        break;
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                    case PerUserState.SERVICE_CONNECTED:
                        // OK, nothing to do.
                        return;
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        return;
                }
                data.mState = PerUserState.SERVICE_RECOGNIZED;
                data.mCurrentInputMethodInfo = imi;
                mInputMethodInfoMap.put(userId, imi);
                final boolean bindResult = data.bindServiceLocked(mContext, userId);
                if (!bindResult) {
                    Slog.e(TAG, "Failed to bind Multi-client InputMethod.");
                    return;
                }
                data.mState = PerUserState.WAITING_SERVICE_CONNECTED;
            }
        }

        @WorkerThread
        void onStartUser(@UserIdInt int userId) {
            if (DEBUG) {
                Slog.v(TAG, "onStartUser userId=" + userId);
            }
            final PerUserData data = new PerUserData(userId, null, PerUserState.USER_LOCKED, this);
            mUserDataMap.put(userId, data);
        }

        @WorkerThread
        void onUnlockUser(@UserIdInt int userId) {
            if (DEBUG) {
                Slog.v(TAG, "onUnlockUser() userId=" + userId);
            }
            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.i(TAG, "onUnlockUser is called for an unknown user=" + userId);
                return;
            }
            synchronized (data.mLock) {
                switch (data.mState) {
                    case PerUserState.USER_LOCKED:
                        data.mState = PerUserState.SERVICE_NOT_QUERIED;
                        tryBindInputMethodService(userId);
                        break;
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        break;
                }
            }
        }

        @WorkerThread
        void onStopUser(@UserIdInt int userId) {
            if (DEBUG) {
                Slog.v(TAG, "onStopUser() userId=" + userId);
            }
            mInputMethodInfoMap.remove(userId);
            final PerUserData data = mUserDataMap.removeReturnOld(userId);
            if (data == null) {
                Slog.i(TAG, "onStopUser is called for an unknown user=" + userId);
                return;
            }
            synchronized (data.mLock) {
                switch (data.mState) {
                    case PerUserState.USER_LOCKED:
                    case PerUserState.SERVICE_RECOGNIZED:
                    case PerUserState.UNBIND_CALLED:
                        // OK, nothing to do.
                        return;
                    case PerUserState.SERVICE_CONNECTED:
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                        break;
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        break;
                }
                data.unbindServiceLocked(mContext);
                data.mState = PerUserState.UNBIND_CALLED;
                data.mCurrentInputMethod = null;

                // When a Service is explicitly unbound with Context.unbindService(),
                // onServiceDisconnected() will not be triggered.  Hence here we explicitly call
                // onInputMethodDisconnectedLocked() as if the Service is already gone.
                data.onInputMethodDisconnectedLocked();
            }
        }

        @WorkerThread
        void onServiceConnected(PerUserData data, IMultiClientInputMethod service) {
            if (DEBUG) {
                Slog.v(TAG, "onServiceConnected() data.mUserId=" + data.mUserId);
            }
            synchronized (data.mLock) {
                switch (data.mState) {
                    case PerUserState.UNBIND_CALLED:
                        // We should ignore this callback.
                        return;
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                        // OK.
                        data.mState = PerUserState.SERVICE_CONNECTED;
                        data.mCurrentInputMethod = service;
                        try {
                            data.mCurrentInputMethod.initialize(new ImeCallbacks(data));
                        } catch (RemoteException e) {
                        }
                        data.onInputMethodConnectedLocked();
                        break;
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        return;
                }
            }
        }

        @WorkerThread
        void onServiceDisconnected(PerUserData data) {
            if (DEBUG) {
                Slog.v(TAG, "onServiceDisconnected() data.mUserId=" + data.mUserId);
            }
            final WindowManagerInternal windowManagerInternal =
                    LocalServices.getService(WindowManagerInternal.class);
            synchronized (data.mLock) {
                // We assume the number of tokens would not be that large (up to 10 or so) hence
                // linear search should be acceptable.
                final int numTokens = data.mDisplayIdToImeWindowTokenMap.size();
                for (int i = 0; i < numTokens; ++i) {
                    final TokenInfo info = data.mDisplayIdToImeWindowTokenMap.valueAt(i);
                    windowManagerInternal.removeWindowToken(info.mToken, false, info.mDisplayId);
                }
                data.mDisplayIdToImeWindowTokenMap.clear();
                switch (data.mState) {
                    case PerUserState.UNBIND_CALLED:
                        // We should ignore this callback.
                        return;
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                    case PerUserState.SERVICE_CONNECTED:
                        // onServiceDisconnected() means the biding is still alive.
                        data.mState = PerUserState.WAITING_SERVICE_CONNECTED;
                        data.mCurrentInputMethod = null;
                        data.onInputMethodDisconnectedLocked();
                        break;
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        return;
                }
            }
        }

        @WorkerThread
        void onBindingDied(PerUserData data) {
            if (DEBUG) {
                Slog.v(TAG, "onBindingDied() data.mUserId=" + data.mUserId);
            }
            final WindowManagerInternal windowManagerInternal =
                    LocalServices.getService(WindowManagerInternal.class);
            synchronized (data.mLock) {
                // We assume the number of tokens would not be that large (up to 10 or so) hence
                // linear search should be acceptable.
                final int numTokens = data.mDisplayIdToImeWindowTokenMap.size();
                for (int i = 0; i < numTokens; ++i) {
                    final TokenInfo info = data.mDisplayIdToImeWindowTokenMap.valueAt(i);
                    windowManagerInternal.removeWindowToken(info.mToken, false, info.mDisplayId);
                }
                data.mDisplayIdToImeWindowTokenMap.clear();
                switch (data.mState) {
                    case PerUserState.UNBIND_CALLED:
                        // We should ignore this callback.
                        return;
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                    case PerUserState.SERVICE_CONNECTED: {
                        // onBindingDied() means the biding is dead.
                        data.mState = PerUserState.UNBIND_CALLED;
                        data.mCurrentInputMethod = null;
                        data.onInputMethodDisconnectedLocked();
                        // Schedule a retry
                        mHandler.sendMessageDelayed(PooledLambda.obtainMessage(
                                OnWorkerThreadCallback::tryBindInputMethodService,
                                this, data.mUserId), RECONNECT_DELAY_MSEC);
                        break;
                    }
                    default:
                        Slog.wtf(TAG, "Unknown state=" + data.mState);
                        return;
                }
            }
        }

        @WorkerThread
        void onBootPhase(int phase) {
            if (DEBUG) {
                Slog.v(TAG, "onBootPhase() phase=" + phase);
            }
            switch (phase) {
                case SystemService.PHASE_ACTIVITY_MANAGER_READY: {
                    final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
                    filter.addDataScheme("package");
                    mContext.registerReceiver(new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            onPackageAdded(intent);
                        }
                    }, filter, null, mHandler);
                    break;
                }
                case SystemService.PHASE_BOOT_COMPLETED: {
                    final boolean perDisplayFocusEnabled = mContext.getResources().getBoolean(
                            com.android.internal.R.bool.config_perDisplayFocusEnabled);
                    if (!perDisplayFocusEnabled) {
                        final Bundle extras = new Bundle();
                        extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
                        mContext.getSystemService(NotificationManager.class).notifyAsUser(TAG,
                                SystemMessageProto.SystemMessage.NOTE_SELECT_INPUT_METHOD,
                                new Notification.Builder(mContext,
                                        SystemNotificationChannels.VIRTUAL_KEYBOARD)
                                        .setContentTitle(PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE)
                                        .setStyle(new Notification.BigTextStyle()
                                                .bigText(PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG))
                                        .setSmallIcon(R.drawable.ic_notification_ime_default)
                                        .setWhen(0)
                                        .setOngoing(true)
                                        .setLocalOnly(true)
                                        .addExtras(extras)
                                        .setCategory(Notification.CATEGORY_SYSTEM)
                                        .setColor(mContext.getColor(
                                                R.color.system_notification_accent_color))
                                        .build(), UserHandle.ALL);
                    }
                    break;
                }
            }
        }

        @WorkerThread
        void onPackageAdded(Intent intent) {
            if (DEBUG) {
                Slog.v(TAG, "onPackageAdded() intent=" + intent);
            }
            final Uri uri = intent.getData();
            if (uri == null) {
                return;
            }
            if (!intent.hasExtra(Intent.EXTRA_UID)) {
                return;
            }
            final String packageName = uri.getSchemeSpecificPart();
            if (sImeComponentName == null
                    || packageName == null
                    || !TextUtils.equals(sImeComponentName.getPackageName(), packageName)) {
                return;
            }
            final int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, 0));
            tryBindInputMethodService(userId);
        }
    }

    private static final class WindowInfo {
        final IBinder mWindowToken;
        final int mWindowHandle;

        WindowInfo(IBinder windowToken, int windowCookie) {
            mWindowToken = windowToken;
            mWindowHandle = windowCookie;
        }
    }

    /**
     * Describes the state of each IME client.
     */
    @Retention(SOURCE)
    @IntDef({InputMethodClientState.REGISTERED,
            InputMethodClientState.WAITING_FOR_IME_SESSION,
            InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT,
            InputMethodClientState.ALREADY_SENT_BIND_RESULT,
            InputMethodClientState.UNREGISTERED})
    private @interface InputMethodClientState {
        /**
         * {@link IInputMethodManager#addClient(IInputMethodClient, IInputContext, int)} is called
         * and this client is now recognized by the system.  When the system lost the connection to
         * the current IME, all the clients need to be re-initialized from this state.
         */
        int REGISTERED = 1;
        /**
         * This client is notified to the current IME with {@link
         * IMultiClientInputMethod#addClient(int, int, int, int)} but the IME is not yet responded
         * with {@link IMultiClientInputMethodPrivilegedOperations#acceptClient(int,
         * IInputMethodSession, IMultiClientInputMethodSession, InputChannel)}.
         */
        int WAITING_FOR_IME_SESSION = 2;
        /**
         * This client is already accepted by the IME but a valid {@link InputBindResult} has not
         * been returned to the client yet.
         */
        int READY_TO_SEND_FIRST_BIND_RESULT = 3;
        /**
         * This client has already received a valid {@link InputBindResult} at least once. This
         * means that the client can directly call {@link IInputMethodSession} IPCs and key events
         * via {@link InputChannel}. When the current IME is unbound, these client end points also
         * need to be cleared.
         */
        int ALREADY_SENT_BIND_RESULT = 4;
        /**
         * The client process is dying.
         */
        int UNREGISTERED = 5;
    }

    private static final class InputMethodClientIdSource {
        @GuardedBy("InputMethodClientIdSource.class")
        private static int sNextValue = 0;

        private InputMethodClientIdSource() {
        }

        static synchronized int getNext() {
            final int result = sNextValue;
            sNextValue++;
            if (sNextValue < 0) {
                sNextValue = 0;
            }
            return result;
        }
    }

    private static final class WindowHandleSource {
        @GuardedBy("WindowHandleSource.class")
        private static int sNextValue = 0;

        private WindowHandleSource() {
        }

        static synchronized int getNext() {
            final int result = sNextValue;
            sNextValue++;
            if (sNextValue < 0) {
                sNextValue = 0;
            }
            return result;
        }
    }

    private static final class InputMethodClientInfo {
        final IInputMethodClient mClient;
        final int mUid;
        final int mPid;
        final int mSelfReportedDisplayId;
        final int mClientId;

        @GuardedBy("PerUserData.mLock")
        @InputMethodClientState
        int mState;
        @GuardedBy("PerUserData.mLock")
        int mBindingSequence;
        @GuardedBy("PerUserData.mLock")
        InputChannel mWriteChannel;
        @GuardedBy("PerUserData.mLock")
        IInputMethodSession mInputMethodSession;
        @GuardedBy("PerUserData.mLock")
        IMultiClientInputMethodSession mMSInputMethodSession;
        @GuardedBy("PerUserData.mLock")
        final WeakHashMap<IBinder, WindowInfo> mWindowMap = new WeakHashMap<>();

        InputMethodClientInfo(IInputMethodClient client, int uid, int pid,
                int selfReportedDisplayId) {
            mClient = client;
            mUid = uid;
            mPid = pid;
            mSelfReportedDisplayId = selfReportedDisplayId;
            mClientId = InputMethodClientIdSource.getNext();
        }

        @GuardedBy("PerUserData.mLock")
        void dumpLocked(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
            ipw.println("mState=" + mState + ",mBindingSequence=" + mBindingSequence
                    + ",mWriteChannel=" + mWriteChannel
                    + ",mInputMethodSession=" + mInputMethodSession
                    + ",mMSInputMethodSession=" + mMSInputMethodSession);
        }
    }

    private static final class UserDataMap {
        @GuardedBy("mMap")
        private final SparseArray<PerUserData> mMap = new SparseArray<>();

        @AnyThread
        @Nullable
        PerUserData get(@UserIdInt int userId) {
            synchronized (mMap) {
                return mMap.get(userId);
            }
        }

        @AnyThread
        void put(@UserIdInt int userId, PerUserData data) {
            synchronized (mMap) {
                mMap.put(userId, data);
            }
        }

        @AnyThread
        @Nullable
        PerUserData removeReturnOld(@UserIdInt int userId) {
            synchronized (mMap) {
                return mMap.removeReturnOld(userId);
            }
        }

        @AnyThread
        void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
            synchronized (mMap) {
                for (int i = 0; i < mMap.size(); i++) {
                    int userId = mMap.keyAt(i);
                    PerUserData data = mMap.valueAt(i);
                    ipw.println("userId=" + userId + ", data=");
                    if (data != null) {
                        ipw.increaseIndent();
                        data.dump(fd, ipw, args);
                        ipw.decreaseIndent();
                    }
                }
            }
        }
    }

    private static final class TokenInfo {
        final Binder mToken;
        final int mDisplayId;
        TokenInfo(Binder token, int displayId) {
            mToken = token;
            mDisplayId = displayId;
        }
    }

    @Retention(SOURCE)
    @IntDef({
            PerUserState.USER_LOCKED,
            PerUserState.SERVICE_NOT_QUERIED,
            PerUserState.SERVICE_RECOGNIZED,
            PerUserState.WAITING_SERVICE_CONNECTED,
            PerUserState.SERVICE_CONNECTED,
            PerUserState.UNBIND_CALLED})
    private @interface PerUserState {
        /**
         * The user is still locked.
         */
        int USER_LOCKED = 1;
        /**
         * The system has not queried whether there is a multi-client IME or not.
         */
        int SERVICE_NOT_QUERIED = 2;
        /**
         * A multi-client IME specified in {@link #PROP_DEBUG_MULTI_CLIENT_IME} is found in the
         * system, but not bound yet.
         */
        int SERVICE_RECOGNIZED = 3;
        /**
         * {@link Context#bindServiceAsUser(Intent, ServiceConnection, int, Handler, UserHandle)} is
         * already called for the IME but
         * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder)} is not yet called
         * back. This includes once the IME is bound but temporarily disconnected as notified with
         * {@link ServiceConnection#onServiceDisconnected(ComponentName)}.
         */
        int WAITING_SERVICE_CONNECTED = 4;
        /**
         * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder)} is already called
         * back. The IME is ready to be used.
         */
        int SERVICE_CONNECTED = 5;
        /**
         * The binding is gone.  Either {@link Context#unbindService(ServiceConnection)} is
         * explicitly called or the system decided to destroy the binding as notified with
         * {@link ServiceConnection#onBindingDied(ComponentName)}.
         */
        int UNBIND_CALLED = 6;
    }

    /**
     * Takes care of per-user state separation.
     */
    private static final class PerUserData {
        final Object mLock = new Object();

        /**
         * User ID (not UID) that is associated with this data.
         */
        @UserIdInt
        private final int mUserId;

        /**
         * {@link IMultiClientInputMethod} of the currently connected multi-client IME.  This
         * must be non-{@code null} only while {@link #mState} is
         * {@link PerUserState#SERVICE_CONNECTED}.
         */
        @Nullable
        @GuardedBy("mLock")
        IMultiClientInputMethod mCurrentInputMethod;

        /**
         * {@link InputMethodInfo} of the currently selected multi-client IME.  This must be
         * non-{@code null} unless {@link #mState} is {@link PerUserState#SERVICE_NOT_QUERIED}.
         */
        @GuardedBy("mLock")
        @Nullable
        InputMethodInfo mCurrentInputMethodInfo;

        /**
         * Describes the current service state.
         */
        @GuardedBy("mLock")
        @PerUserState
        int mState;

        /**
         * A {@link SparseArray} that maps display ID to IME Window token that is already issued to
         * the IME.
         */
        @GuardedBy("mLock")
        final ArraySet<TokenInfo> mDisplayIdToImeWindowTokenMap = new ArraySet<>();

        @GuardedBy("mLock")
        private final ArrayMap<IBinder, InputMethodClientInfo> mClientMap = new ArrayMap<>();

        @GuardedBy("mLock")
        private SparseArray<InputMethodClientInfo> mClientIdToClientMap = new SparseArray<>();

        private final OnWorkerThreadServiceConnection mOnWorkerThreadServiceConnection;

        /**
         * A {@link ServiceConnection} that is designed to run on a certain worker thread with
         * which {@link OnWorkerThreadCallback} is associated.
         *
         * @see Context#bindServiceAsUser(Intent, ServiceConnection, int, Handler, UserHandle).
         */
        private static final class OnWorkerThreadServiceConnection implements ServiceConnection {
            private final PerUserData mData;
            private final OnWorkerThreadCallback mCallback;

            OnWorkerThreadServiceConnection(PerUserData data, OnWorkerThreadCallback callback) {
                mData = data;
                mCallback = callback;
            }

            @WorkerThread
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mCallback.onServiceConnected(mData,
                        IMultiClientInputMethod.Stub.asInterface(service));
            }

            @WorkerThread
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mCallback.onServiceDisconnected(mData);
            }

            @WorkerThread
            @Override
            public void onBindingDied(ComponentName name) {
                mCallback.onBindingDied(mData);
            }

            Handler getHandler() {
                return mCallback.getHandler();
            }
        }

        PerUserData(@UserIdInt int userId, @Nullable InputMethodInfo inputMethodInfo,
                @PerUserState int initialState, OnWorkerThreadCallback callback) {
            mUserId = userId;
            mCurrentInputMethodInfo = inputMethodInfo;
            mState = initialState;
            mOnWorkerThreadServiceConnection =
                    new OnWorkerThreadServiceConnection(this, callback);
        }

        @GuardedBy("mLock")
        boolean bindServiceLocked(Context context, @UserIdInt int userId) {
            final Intent intent =
                    new Intent(MultiClientInputMethodServiceDelegate.SERVICE_INTERFACE)
                            .setComponent(mCurrentInputMethodInfo.getComponent())
                            .putExtra(Intent.EXTRA_CLIENT_LABEL,
                                    com.android.internal.R.string.input_method_binding_label)
                            .putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
                                    context, 0,
                                    new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));

            // Note: Instead of re-dispatching callback from the main thread to the worker thread
            // where OnWorkerThreadCallback is running, we pass the Handler object here so that
            // the callbacks will be directly dispatched to the worker thread.
            return context.bindServiceAsUser(intent, mOnWorkerThreadServiceConnection,
                    IME_CONNECTION_UNIFIED_BIND_FLAGS,
                    mOnWorkerThreadServiceConnection.getHandler(), UserHandle.of(userId));
        }

        @GuardedBy("mLock")
        void unbindServiceLocked(Context context) {
            context.unbindService(mOnWorkerThreadServiceConnection);
        }

        @GuardedBy("mLock")
        @Nullable
        InputMethodClientInfo getClientLocked(IInputMethodClient client) {
            return mClientMap.get(client.asBinder());
        }

        @GuardedBy("mLock")
        @Nullable
        InputMethodClientInfo getClientFromIdLocked(int clientId) {
            return mClientIdToClientMap.get(clientId);
        }

        @GuardedBy("mLock")
        @Nullable
        InputMethodClientInfo removeClientLocked(IInputMethodClient client) {
            final InputMethodClientInfo info = mClientMap.remove(client.asBinder());
            if (info != null) {
                mClientIdToClientMap.remove(info.mClientId);
            }
            return info;
        }

        @GuardedBy("mLock")
        void addClientLocked(int uid, int pid, IInputMethodClient client,
                int selfReportedDisplayId) {
            if (getClientLocked(client) != null) {
                Slog.wtf(TAG, "The same client is added multiple times");
                return;
            }
            final ClientDeathRecipient deathRecipient = new ClientDeathRecipient(this, client);
            try {
                client.asBinder().linkToDeath(deathRecipient, 0);
            } catch (RemoteException e) {
                throw new IllegalStateException(e);
            }
            final InputMethodClientInfo clientInfo =
                    new InputMethodClientInfo(client, uid, pid, selfReportedDisplayId);
            clientInfo.mState = InputMethodClientState.REGISTERED;
            mClientMap.put(client.asBinder(), clientInfo);
            mClientIdToClientMap.put(clientInfo.mClientId, clientInfo);
            switch (mState) {
                case PerUserState.SERVICE_CONNECTED:
                    try {
                        mCurrentInputMethod.addClient(
                                clientInfo.mClientId, clientInfo.mPid, clientInfo.mUid,
                                clientInfo.mSelfReportedDisplayId);
                        clientInfo.mState = InputMethodClientState.WAITING_FOR_IME_SESSION;
                    } catch (RemoteException e) {
                        // TODO(yukawa): Need logging and expected behavior
                    }
                    break;
            }
        }

        @GuardedBy("mLock")
        void onInputMethodConnectedLocked() {
            final int numClients = mClientMap.size();
            for (int i = 0; i < numClients; ++i) {
                final InputMethodClientInfo clientInfo = mClientMap.valueAt(i);
                switch (clientInfo.mState) {
                    case InputMethodClientState.REGISTERED:
                        // OK
                        break;
                    default:
                        Slog.e(TAG, "Unexpected state=" + clientInfo.mState);
                        return;
                }
                try {
                    mCurrentInputMethod.addClient(
                            clientInfo.mClientId, clientInfo.mUid, clientInfo.mPid,
                            clientInfo.mSelfReportedDisplayId);
                    clientInfo.mState = InputMethodClientState.WAITING_FOR_IME_SESSION;
                } catch (RemoteException e) {
                }
            }
        }

        @GuardedBy("mLock")
        void onInputMethodDisconnectedLocked() {
            final int numClients = mClientMap.size();
            for (int i = 0; i < numClients; ++i) {
                final InputMethodClientInfo clientInfo = mClientMap.valueAt(i);
                switch (clientInfo.mState) {
                    case InputMethodClientState.REGISTERED:
                        // Disconnected before onInputMethodConnectedLocked().
                        break;
                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
                        // Disconnected between addClient() and acceptClient().
                        clientInfo.mState = InputMethodClientState.REGISTERED;
                        break;
                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
                        clientInfo.mState = InputMethodClientState.REGISTERED;
                        clientInfo.mInputMethodSession = null;
                        clientInfo.mMSInputMethodSession = null;
                        if (clientInfo.mWriteChannel != null) {
                            clientInfo.mWriteChannel.dispose();
                            clientInfo.mWriteChannel = null;
                        }
                        break;
                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
                        try {
                            clientInfo.mClient.onUnbindMethod(clientInfo.mBindingSequence,
                                    UnbindReason.DISCONNECT_IME);
                        } catch (RemoteException e) {
                        }
                        clientInfo.mState = InputMethodClientState.REGISTERED;
                        clientInfo.mInputMethodSession = null;
                        clientInfo.mMSInputMethodSession = null;
                        if (clientInfo.mWriteChannel != null) {
                            clientInfo.mWriteChannel.dispose();
                            clientInfo.mWriteChannel = null;
                        }
                        break;
                }
            }
        }

        @AnyThread
        void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
            synchronized (mLock) {
                ipw.println("mState=" + mState
                        + ",mCurrentInputMethod=" + mCurrentInputMethod
                        + ",mCurrentInputMethodInfo=" + mCurrentInputMethodInfo);

                if (mCurrentInputMethod != null) {
                    // indentation will not be kept. So add visual separator here.
                    ipw.println(">>Dump CurrentInputMethod>>");
                    ipw.flush();
                    try {
                        TransferPipe.dumpAsync(mCurrentInputMethod.asBinder(), fd, args);
                    } catch (IOException | RemoteException e) {
                        ipw.println("Failed to dump input method service: " + e);
                    }
                    ipw.println("<<Dump CurrentInputMethod<<");
                }

                ipw.println("mDisplayIdToImeWindowTokenMap=");
                for (TokenInfo info : mDisplayIdToImeWindowTokenMap) {
                    ipw.println(" display=" + info.mDisplayId + ",token="
                            + info.mToken);
                }
                ipw.println("mClientMap=");
                ipw.increaseIndent();
                for (int i = 0; i < mClientMap.size(); i++) {

                    ipw.println("binder=" + mClientMap.keyAt(i));
                    ipw.println(" InputMethodClientInfo=");
                    InputMethodClientInfo info = mClientMap.valueAt(i);
                    if (info != null) {
                        ipw.increaseIndent();
                        info.dumpLocked(fd, ipw, args);
                        ipw.decreaseIndent();
                    }
                }
                ipw.decreaseIndent();
                ipw.println("mClientIdToClientMap=");
                ipw.increaseIndent();
                for (int i = 0; i < mClientIdToClientMap.size(); i++) {
                    ipw.println("clientId=" + mClientIdToClientMap.keyAt(i));
                    ipw.println(" InputMethodClientInfo=");
                    InputMethodClientInfo info = mClientIdToClientMap.valueAt(i);
                    if (info != null) {
                        ipw.increaseIndent();
                        info.dumpLocked(fd, ipw, args);
                        ipw.decreaseIndent();
                    }
                    if (info.mClient != null) {
                        // indentation will not be kept. So add visual separator here.
                        ipw.println(">>DumpClientStart>>");
                        ipw.flush(); // all writes should be flushed to guarantee order.
                        try {
                            TransferPipe.dumpAsync(info.mClient.asBinder(), fd, args);
                        } catch (IOException | RemoteException e) {
                            ipw.println(" Failed to dump client:" + e);
                        }
                        ipw.println("<<DumpClientEnd<<");
                    }
                }
                ipw.decreaseIndent();
            }
        }

        private static final class ClientDeathRecipient implements IBinder.DeathRecipient {
            private final PerUserData mPerUserData;
            private final IInputMethodClient mClient;

            ClientDeathRecipient(PerUserData perUserData, IInputMethodClient client) {
                mPerUserData = perUserData;
                mClient = client;
            }

            @BinderThread
            @Override
            public void binderDied() {
                synchronized (mPerUserData.mLock) {
                    mClient.asBinder().unlinkToDeath(this, 0);

                    final InputMethodClientInfo clientInfo =
                            mPerUserData.removeClientLocked(mClient);
                    if (clientInfo == null) {
                        return;
                    }

                    if (clientInfo.mWriteChannel != null) {
                        clientInfo.mWriteChannel.dispose();
                        clientInfo.mWriteChannel = null;
                    }
                    if (clientInfo.mInputMethodSession != null) {
                        try {
                            clientInfo.mInputMethodSession.finishSession();
                        } catch (RemoteException e) {
                        }
                        clientInfo.mInputMethodSession = null;
                    }
                    clientInfo.mMSInputMethodSession = null;
                    clientInfo.mState = InputMethodClientState.UNREGISTERED;
                    switch (mPerUserData.mState) {
                        case PerUserState.SERVICE_CONNECTED:
                            try {
                                mPerUserData.mCurrentInputMethod.removeClient(clientInfo.mClientId);
                            } catch (RemoteException e) {
                                // TODO(yukawa): Need logging and expected behavior
                            }
                            break;
                    }
                }
            }
        }
    }

    /**
     * Queries for multi-client IME specified with {@code componentName}.
     *
     * @param context {@link Context} to be used to query component.
     * @param userId User ID for which the multi-client IME is queried.
     * @param componentName {@link ComponentName} to be queried.
     * @return {@link InputMethodInfo} when multi-client IME is found. Otherwise {@code null}.
     */
    @Nullable
    private static InputMethodInfo queryInputMethod(Context context, @UserIdInt int userId,
            @Nullable ComponentName componentName) {
        if (componentName == null) {
            return null;
        }

        // Use for queryIntentServicesAsUser
        final PackageManager pm = context.getPackageManager();
        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                new Intent(MultiClientInputMethodServiceDelegate.SERVICE_INTERFACE)
                        .setComponent(componentName),
                PackageManager.GET_META_DATA, userId);

        if (services.isEmpty()) {
            Slog.e(TAG, "No IME found");
            return null;
        }

        if (services.size() > 1) {
            Slog.e(TAG, "Only one IME service is supported.");
            return null;
        }

        final ResolveInfo ri = services.get(0);
        ServiceInfo si = ri.serviceInfo;
        final String imeId = InputMethodInfo.computeId(ri);
        if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
            Slog.e(TAG, imeId + " must have required"
                    + android.Manifest.permission.BIND_INPUT_METHOD);
            return null;
        }

        if (!Build.IS_DEBUGGABLE && (si.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            Slog.e(TAG, imeId + " must be pre-installed when Build.IS_DEBUGGABLE is false");
            return null;
        }

        try {
            return new InputMethodInfo(context, ri);
        } catch (Exception e) {
            Slog.wtf(TAG, "Unable to load input method " + imeId, e);
        }
        return null;
    }

    /**
     * Manages the mapping rule from user ID to {@link InputMethodInfo}.
     */
    private static final class UserToInputMethodInfoMap {
        @GuardedBy("mArray")
        private final SparseArray<InputMethodInfo> mArray = new SparseArray<>();

        @AnyThread
        void put(@UserIdInt int userId, InputMethodInfo imi) {
            synchronized (mArray) {
                mArray.put(userId, imi);
            }
        }

        @AnyThread
        void remove(@UserIdInt int userId) {
            synchronized (mArray) {
                mArray.remove(userId);
            }
        }

        @AnyThread
        @Nullable
        InputMethodInfo get(@UserIdInt int userId) {
            synchronized (mArray) {
                return mArray.get(userId);
            }
        }

        @AnyThread
        List<InputMethodInfo> getAsList(@UserIdInt int userId) {
            final InputMethodInfo info = get(userId);
            if (info == null) {
                return Collections.emptyList();
            }
            return Collections.singletonList(info);
        }

        @AnyThread
        void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) {
            synchronized (mArray) {
                for (int i = 0; i < mArray.size(); i++) {
                    ipw.println("userId=" + mArray.keyAt(i));
                    ipw.println(" InputMethodInfo=" + mArray.valueAt(i));
                }
            }
        }
    }

    /**
     * Takes care of IPCs exposed to the multi-client IME.
     */
    private static final class ImeCallbacks
            extends IMultiClientInputMethodPrivilegedOperations.Stub {
        private final PerUserData mPerUserData;
        private final WindowManagerInternal mIWindowManagerInternal;

        ImeCallbacks(PerUserData perUserData) {
            mPerUserData = perUserData;
            mIWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        }

        @BinderThread
        @Override
        public IBinder createInputMethodWindowToken(int displayId) {
            synchronized (mPerUserData.mLock) {
                // We assume the number of tokens would not be that large (up to 10 or so) hence
                // linear search should be acceptable.
                final int numTokens = mPerUserData.mDisplayIdToImeWindowTokenMap.size();
                for (int i = 0; i < numTokens; ++i) {
                    final TokenInfo tokenInfo =
                            mPerUserData.mDisplayIdToImeWindowTokenMap.valueAt(i);
                    // Currently we issue up to one window token per display.
                    if (tokenInfo.mDisplayId == displayId) {
                        return tokenInfo.mToken;
                    }
                }

                final Binder token = new Binder();
                Binder.withCleanCallingIdentity(
                        PooledLambda.obtainRunnable(WindowManagerInternal::addWindowToken,
                                mIWindowManagerInternal, token, TYPE_INPUT_METHOD, displayId));
                mPerUserData.mDisplayIdToImeWindowTokenMap.add(new TokenInfo(token, displayId));
                return token;
            }
        }

        @BinderThread
        @Override
        public void deleteInputMethodWindowToken(IBinder token) {
            synchronized (mPerUserData.mLock) {
                // We assume the number of tokens would not be that large (up to 10 or so) hence
                // linear search should be acceptable.
                final int numTokens = mPerUserData.mDisplayIdToImeWindowTokenMap.size();
                for (int i = 0; i < numTokens; ++i) {
                    final TokenInfo tokenInfo =
                            mPerUserData.mDisplayIdToImeWindowTokenMap.valueAt(i);
                    if (tokenInfo.mToken == token) {
                        mPerUserData.mDisplayIdToImeWindowTokenMap.remove(tokenInfo);
                        break;
                    }
                }
            }
        }

        @BinderThread
        @Override
        public void acceptClient(int clientId, IInputMethodSession inputMethodSession,
                IMultiClientInputMethodSession multiSessionInputMethodSession,
                InputChannel writeChannel) {
            synchronized (mPerUserData.mLock) {
                final InputMethodClientInfo clientInfo =
                        mPerUserData.getClientFromIdLocked(clientId);
                if (clientInfo == null) {
                    Slog.e(TAG, "Unknown clientId=" + clientId);
                    return;
                }
                switch (clientInfo.mState) {
                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
                        try {
                            clientInfo.mClient.setActive(true, false);
                        } catch (RemoteException e) {
                            // TODO(yukawa): Remove this client.
                            return;
                        }
                        clientInfo.mState = InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT;
                        clientInfo.mWriteChannel = writeChannel;
                        clientInfo.mInputMethodSession = inputMethodSession;
                        clientInfo.mMSInputMethodSession = multiSessionInputMethodSession;
                        break;
                    default:
                        Slog.e(TAG, "Unexpected state=" + clientInfo.mState);
                        break;
                }
            }
        }

        @BinderThread
        @Override
        public void reportImeWindowTarget(int clientId, int targetWindowHandle,
                IBinder imeWindowToken) {
            synchronized (mPerUserData.mLock) {
                final InputMethodClientInfo clientInfo =
                        mPerUserData.getClientFromIdLocked(clientId);
                if (clientInfo == null) {
                    Slog.e(TAG, "Unknown clientId=" + clientId);
                    return;
                }
                for (WindowInfo windowInfo : clientInfo.mWindowMap.values()) {
                    if (windowInfo.mWindowHandle == targetWindowHandle) {
                        final IBinder targetWindowToken = windowInfo.mWindowToken;
                        // TODO(yukawa): Report targetWindowToken and targetWindowToken to WMS.
                        if (DEBUG) {
                            Slog.v(TAG, "reportImeWindowTarget"
                                    + " clientId=" + clientId
                                    + " imeWindowToken=" + imeWindowToken
                                    + " targetWindowToken=" + targetWindowToken);
                        }
                    }
                }
                // not found.
            }
        }

        @BinderThread
        @Override
        public boolean isUidAllowedOnDisplay(int displayId, int uid) {
            return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
        }

        @BinderThread
        @Override
        public void setActive(int clientId, boolean active) {
            synchronized (mPerUserData.mLock) {
                final InputMethodClientInfo clientInfo =
                        mPerUserData.getClientFromIdLocked(clientId);
                if (clientInfo == null) {
                    Slog.e(TAG, "Unknown clientId=" + clientId);
                    return;
                }
                try {
                    clientInfo.mClient.setActive(active, false /* fullscreen */);
                } catch (RemoteException e) {
                    return;
                }
            }
        }
    }

    /**
     * Takes care of IPCs exposed to the IME client.
     */
    private static final class ApiCallbacks extends IInputMethodManager.Stub {
        private final Context mContext;
        private final UserDataMap mUserDataMap;
        private final UserToInputMethodInfoMap mInputMethodInfoMap;
        private final AppOpsManager mAppOpsManager;
        private final WindowManagerInternal mWindowManagerInternal;

        ApiCallbacks(Context context, UserDataMap userDataMap,
                UserToInputMethodInfoMap inputMethodInfoMap) {
            mContext = context;
            mUserDataMap = userDataMap;
            mInputMethodInfoMap = inputMethodInfoMap;
            mAppOpsManager = context.getSystemService(AppOpsManager.class);
            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        }

        @AnyThread
        private boolean checkFocus(int uid, int pid, int displayId) {
            return mWindowManagerInternal.isInputMethodClientFocus(uid, pid, displayId);
        }

        @BinderThread
        @Override
        public void addClient(IInputMethodClient client, IInputContext inputContext,
                int selfReportedDisplayId) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int userId = UserHandle.getUserId(callingUid);
            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.e(TAG, "addClient() from unknown userId=" + userId
                        + " uid=" + callingUid + " pid=" + callingPid);
                return;
            }
            synchronized (data.mLock) {
                data.addClientLocked(callingUid, callingPid, client, selfReportedDisplayId);
            }
        }

        @BinderThread
        @Override
        public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) {
            if (UserHandle.getCallingUserId() != userId) {
                mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, null);
            }
            return mInputMethodInfoMap.getAsList(userId);
        }

        @BinderThread
        @Override
        public List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) {
            if (UserHandle.getCallingUserId() != userId) {
                mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, null);
            }
            return mInputMethodInfoMap.getAsList(userId);
        }

        @BinderThread
        @Override
        public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
                boolean allowsImplicitlySelectedSubtypes) {
            reportNotSupported();
            return Collections.emptyList();
        }

        @BinderThread
        @Override
        public InputMethodSubtype getLastInputMethodSubtype() {
            reportNotSupported();
            return null;
        }

        @BinderThread
        @Override
        public boolean showSoftInput(
                IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int userId = UserHandle.getUserId(callingUid);
            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.e(TAG, "showSoftInput() from unknown userId=" + userId
                        + " uid=" + callingUid + " pid=" + callingPid);
                return false;
            }
            synchronized (data.mLock) {
                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
                if (clientInfo == null) {
                    Slog.e(TAG, "showSoftInput. client not found. ignoring.");
                    return false;
                }
                if (clientInfo.mUid != callingUid) {
                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
                            + " actual=" + callingUid);
                    return false;
                }
                switch (clientInfo.mState) {
                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
                        try {
                            clientInfo.mMSInputMethodSession.showSoftInput(flags, resultReceiver);
                        } catch (RemoteException e) {
                        }
                        break;
                    default:
                        if (DEBUG) {
                            Slog.e(TAG, "Ignoring showSoftInput(). clientState="
                                    + clientInfo.mState);
                        }
                        break;
                }
                return true;
            }
        }

        @BinderThread
        @Override
        public boolean hideSoftInput(
                IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int userId = UserHandle.getUserId(callingUid);
            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.e(TAG, "hideSoftInput() from unknown userId=" + userId
                        + " uid=" + callingUid + " pid=" + callingPid);
                return false;
            }
            synchronized (data.mLock) {
                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
                if (clientInfo == null) {
                    return false;
                }
                if (clientInfo.mUid != callingUid) {
                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
                            + " actual=" + callingUid);
                    return false;
                }
                switch (clientInfo.mState) {
                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
                        try {
                            clientInfo.mMSInputMethodSession.hideSoftInput(flags, resultReceiver);
                        } catch (RemoteException e) {
                        }
                        break;
                    default:
                        if (DEBUG) {
                            Slog.e(TAG, "Ignoring hideSoftInput(). clientState="
                                    + clientInfo.mState);
                        }
                        break;
                }
                return true;
            }
        }

        @BinderThread
        @Override
        public InputBindResult startInputOrWindowGainedFocus(
                @StartInputReason int startInputReason,
                @Nullable IInputMethodClient client,
                @Nullable IBinder windowToken,
                @StartInputFlags int startInputFlags,
                @SoftInputModeFlags int softInputMode,
                int windowFlags,
                @Nullable EditorInfo editorInfo,
                @Nullable IInputContext inputContext,
                @MissingMethodFlags int missingMethods,
                int unverifiedTargetSdkVersion) {
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int userId = UserHandle.getUserId(callingUid);

            if (client == null) {
                return InputBindResult.INVALID_CLIENT;
            }

            final boolean packageNameVerified =
                    editorInfo != null && InputMethodUtils.checkIfPackageBelongsToUid(
                            mAppOpsManager, callingUid, editorInfo.packageName);
            if (editorInfo != null && !packageNameVerified) {
                Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
                        + " uid=" + callingUid + " package=" + editorInfo.packageName);
                return InputBindResult.INVALID_PACKAGE_NAME;
            }

            final PerUserData data = mUserDataMap.get(userId);
            if (data == null) {
                Slog.e(TAG, "startInputOrWindowGainedFocus() from unknown userId=" + userId
                        + " uid=" + callingUid + " pid=" + callingPid);
                return InputBindResult.INVALID_USER;
            }

            synchronized (data.mLock) {
                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
                if (clientInfo == null) {
                    return InputBindResult.INVALID_CLIENT;
                }
                if (clientInfo.mUid != callingUid) {
                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
                            + " actual=" + callingUid);
                    return InputBindResult.INVALID_CLIENT;
                }

                switch (data.mState) {
                    case PerUserState.USER_LOCKED:
                    case PerUserState.SERVICE_NOT_QUERIED:
                    case PerUserState.SERVICE_RECOGNIZED:
                    case PerUserState.WAITING_SERVICE_CONNECTED:
                    case PerUserState.UNBIND_CALLED:
                        return InputBindResult.IME_NOT_CONNECTED;
                    case PerUserState.SERVICE_CONNECTED:
                        // OK
                        break;
                    default:
                        Slog.wtf(TAG, "Unexpected state=" + data.mState);
                        return InputBindResult.IME_NOT_CONNECTED;
                }

                WindowInfo windowInfo = null;
                if (windowToken != null) {
                    windowInfo = clientInfo.mWindowMap.get(windowToken);
                    if (windowInfo == null) {
                        windowInfo = new WindowInfo(windowToken, WindowHandleSource.getNext());
                        clientInfo.mWindowMap.put(windowToken, windowInfo);
                    }
                }

                if (!checkFocus(clientInfo.mUid, clientInfo.mPid,
                        clientInfo.mSelfReportedDisplayId)) {
                    return InputBindResult.NOT_IME_TARGET_WINDOW;
                }

                if (editorInfo == null) {
                    // So-called dummy InputConnection scenario.  For app compatibility, we still
                    // notify this to the IME.
                    switch (clientInfo.mState) {
                        case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
                        case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
                            final int windowHandle = windowInfo != null
                                    ? windowInfo.mWindowHandle
                                    : MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
                            try {
                                clientInfo.mMSInputMethodSession.startInputOrWindowGainedFocus(
                                        inputContext, missingMethods, editorInfo, startInputFlags,
                                        softInputMode, windowHandle);
                            } catch (RemoteException e) {
                            }
                            break;
                    }
                    return InputBindResult.NULL_EDITOR_INFO;
                }

                switch (clientInfo.mState) {
                    case InputMethodClientState.REGISTERED:
                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
                        clientInfo.mBindingSequence++;
                        if (clientInfo.mBindingSequence < 0) {
                            clientInfo.mBindingSequence = 0;
                        }
                        return new InputBindResult(
                                InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
                                null, null, data.mCurrentInputMethodInfo.getId(),
                                clientInfo.mBindingSequence);
                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
                        clientInfo.mBindingSequence++;
                        if (clientInfo.mBindingSequence < 0) {
                            clientInfo.mBindingSequence = 0;
                        }
                        // Successful start input.
                        final int windowHandle = windowInfo != null
                                ? windowInfo.mWindowHandle
                                : MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
                        try {
                            clientInfo.mMSInputMethodSession.startInputOrWindowGainedFocus(
                                    inputContext, missingMethods, editorInfo, startInputFlags,
                                    softInputMode, windowHandle);
                        } catch (RemoteException e) {
                        }
                        clientInfo.mState = InputMethodClientState.ALREADY_SENT_BIND_RESULT;
                        return new InputBindResult(
                                InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
                                clientInfo.mInputMethodSession,
                                clientInfo.mWriteChannel.dup(),
                                data.mCurrentInputMethodInfo.getId(),
                                clientInfo.mBindingSequence);
                    case InputMethodClientState.UNREGISTERED:
                        Slog.e(TAG, "The client is already unregistered.");
                        return InputBindResult.INVALID_CLIENT;
                }
            }
            return null;
        }

        @BinderThread
        @Override
        public void showInputMethodPickerFromClient(
                IInputMethodClient client, int auxiliarySubtypeMode) {
            reportNotSupported();
        }

        @BinderThread
        @Override
        public void showInputMethodPickerFromSystem(
                IInputMethodClient client, int auxiliarySubtypeMode, int displayId) {
            reportNotSupported();
        }

        @BinderThread
        @Override
        public void showInputMethodAndSubtypeEnablerFromClient(
                IInputMethodClient client, String inputMethodId) {
            reportNotSupported();
        }

        @BinderThread
        @Override
        public boolean isInputMethodPickerShownForTest() {
            reportNotSupported();
            return false;
        }

        @BinderThread
        @Override
        public InputMethodSubtype getCurrentInputMethodSubtype() {
            reportNotSupported();
            return null;
        }

        @BinderThread
        @Override
        public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
            reportNotSupported();
        }

        @BinderThread
        @Override
        public int getInputMethodWindowVisibleHeight() {
            reportNotSupported();
            return 0;
        }

        @BinderThread
        @Override
        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
                @Nullable FileDescriptor err, String[] args, @Nullable ShellCallback callback,
                ResultReceiver resultReceiver) {
        }

        @BinderThread
        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
            final String prefixChild = "  ";
            pw.println("Current Multi Client Input Method Manager state:");
            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
            ipw.println("mUserDataMap=");
            if (mUserDataMap != null) {
                ipw.increaseIndent();
                mUserDataMap.dump(fd, ipw, args);
            }
        }
    }
}
