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

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
import android.service.voice.VoiceInteractionSession;
import android.speech.RecognitionService;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.TimingsTraceLog;

import com.android.internal.app.IVoiceActionCheckCallback;
import com.android.internal.app.IVoiceInteractionManagerService;
import com.android.internal.app.IVoiceInteractionSessionListener;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.soundtrigger.SoundTriggerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * SystemService that publishes an IVoiceInteractionManagerService.
 */
public class VoiceInteractionManagerService extends SystemService {
    static final String TAG = "VoiceInteractionManagerService";
    static final boolean DEBUG = false;

    final Context mContext;
    final ContentResolver mResolver;
    final DatabaseHelper mDbHelper;
    final ActivityManagerInternal mAmInternal;
    final ActivityTaskManagerInternal mAtmInternal;
    final UserManager mUserManager;
    final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>();
    ShortcutServiceInternal mShortcutServiceInternal;
    SoundTriggerInternal mSoundTriggerInternal;

    private final RemoteCallbackList<IVoiceInteractionSessionListener>
            mVoiceInteractionSessionListeners = new RemoteCallbackList<>();

    public VoiceInteractionManagerService(Context context) {
        super(context);
        mContext = context;
        mResolver = context.getContentResolver();
        mDbHelper = new DatabaseHelper(context);
        mServiceStub = new VoiceInteractionManagerServiceStub();
        mAmInternal = Preconditions.checkNotNull(
                LocalServices.getService(ActivityManagerInternal.class));
        mAtmInternal = Preconditions.checkNotNull(
                LocalServices.getService(ActivityTaskManagerInternal.class));
        mUserManager = Preconditions.checkNotNull(
                context.getSystemService(UserManager.class));

        PackageManagerInternal packageManagerInternal = LocalServices.getService(
                PackageManagerInternal.class);
        packageManagerInternal.setVoiceInteractionPackagesProvider(
                new PackageManagerInternal.PackagesProvider() {
            @Override
            public String[] getPackages(int userId) {
                mServiceStub.initForUser(userId);
                ComponentName interactor = mServiceStub.getCurInteractor(userId);
                if (interactor != null) {
                    return new String[] {interactor.getPackageName()};
                }
                return null;
            }
        });
    }

    @Override
    public void onStart() {
        publishBinderService(Context.VOICE_INTERACTION_MANAGER_SERVICE, mServiceStub);
        publishLocalService(VoiceInteractionManagerInternal.class, new LocalService());
    }

    @Override
    public void onBootPhase(int phase) {
        if (PHASE_SYSTEM_SERVICES_READY == phase) {
            mShortcutServiceInternal = Preconditions.checkNotNull(
                    LocalServices.getService(ShortcutServiceInternal.class));
            mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
        } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            mServiceStub.systemRunning(isSafeMode());
        }
    }

    @Override
    public void onStartUser(int userHandle) {
        mServiceStub.initForUser(userHandle);
    }

    @Override
    public void onUnlockUser(int userHandle) {
        mServiceStub.initForUser(userHandle);
        mServiceStub.switchImplementationIfNeeded(false);
    }

    @Override
    public void onSwitchUser(int userHandle) {
        mServiceStub.switchUser(userHandle);
    }

    class LocalService extends VoiceInteractionManagerInternal {
        @Override
        public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
            if (DEBUG) {
                Slog.i(TAG, "startLocalVoiceInteraction " + callingActivity);
            }
            VoiceInteractionManagerService.this.mServiceStub.startLocalVoiceInteraction(
                    callingActivity, options);
        }

        @Override
        public boolean supportsLocalVoiceInteraction() {
            return VoiceInteractionManagerService.this.mServiceStub.supportsLocalVoiceInteraction();
        }

        @Override
        public void stopLocalVoiceInteraction(IBinder callingActivity) {
            if (DEBUG) {
                Slog.i(TAG, "stopLocalVoiceInteraction " + callingActivity);
            }
            VoiceInteractionManagerService.this.mServiceStub.stopLocalVoiceInteraction(
                    callingActivity);
        }
    }

    // implementation entry point and binder service
    private final VoiceInteractionManagerServiceStub mServiceStub;

    class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {

        VoiceInteractionManagerServiceImpl mImpl;

        private boolean mSafeMode;
        private int mCurUser;
        private boolean mCurUserUnlocked;
        private final boolean mEnableService;

        VoiceInteractionManagerServiceStub() {
            mEnableService = shouldEnableService(mContext);
            new RoleObserver(mContext.getMainExecutor());
        }

        // TODO: VI Make sure the caller is the current user or profile
        void startLocalVoiceInteraction(final IBinder token, Bundle options) {
            if (mImpl == null) return;

            final long caller = Binder.clearCallingIdentity();
            try {
                mImpl.showSessionLocked(options,
                        VoiceInteractionSession.SHOW_SOURCE_ACTIVITY,
                        new IVoiceInteractionSessionShowCallback.Stub() {
                            @Override
                            public void onFailed() {
                            }

                            @Override
                            public void onShown() {
                                mAtmInternal.onLocalVoiceInteractionStarted(token,
                                        mImpl.mActiveSession.mSession,
                                        mImpl.mActiveSession.mInteractor);
                            }
                        },
                        token);
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        public void stopLocalVoiceInteraction(IBinder callingActivity) {
            if (mImpl == null) return;

            final long caller = Binder.clearCallingIdentity();
            try {
                mImpl.finishLocked(callingActivity, true);
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        public boolean supportsLocalVoiceInteraction() {
            if (mImpl == null) return false;

            return mImpl.supportsLocalVoiceInteraction();
        }

        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
            try {
                return super.onTransact(code, data, reply, flags);
            } catch (RuntimeException e) {
                // The activity manager only throws security exceptions, so let's
                // log all others.
                if (!(e instanceof SecurityException)) {
                    Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
                }
                throw e;
            }
        }

        public void initForUser(@UserIdInt int userHandle) {
            final TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            t.traceBegin("initForUser(" + userHandle + ")");
            try {
                initForUserNoTracing(userHandle);
            } finally {
                t.traceEnd();
            }
        }

        private void initForUserNoTracing(@UserIdInt int userHandle) {
            if (DEBUG) Slog.d(TAG, "**************** initForUser user=" + userHandle);
            String curInteractorStr = Settings.Secure.getStringForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
            ComponentName curRecognizer = getCurRecognizer(userHandle);
            VoiceInteractionServiceInfo curInteractorInfo = null;
            if (DEBUG) Slog.d(TAG, "curInteractorStr=" + curInteractorStr
                    + " curRecognizer=" + curRecognizer);
            if (curInteractorStr == null && curRecognizer != null && mEnableService) {
                // If there is no interactor setting, that means we are upgrading
                // from an older platform version.  If the current recognizer is not
                // set or matches the preferred recognizer, then we want to upgrade
                // the user to have the default voice interaction service enabled.
                // Note that we don't do this for low-RAM devices, since we aren't
                // supporting voice interaction services there.
                curInteractorInfo = findAvailInteractor(userHandle, curRecognizer.getPackageName());
                if (curInteractorInfo != null) {
                    // Looks good!  We'll apply this one.  To make it happen, we clear the
                    // recognizer so that we don't think we have anything set and will
                    // re-apply the settings.
                    if (DEBUG) Slog.d(TAG, "No set interactor, found avail: "
                            + curInteractorInfo.getServiceInfo().name);
                    curRecognizer = null;
                }
            }

            // If forceInteractorPackage exists, try to apply the interactor from this package if
            // possible and ignore the regular interactor setting.
            String forceInteractorPackage =
                    getForceVoiceInteractionServicePackage(mContext.getResources());
            if (forceInteractorPackage != null) {
                curInteractorInfo = findAvailInteractor(userHandle, forceInteractorPackage);
                if (curInteractorInfo != null) {
                    // We'll apply this one. Clear the recognizer and re-apply the settings.
                    curRecognizer = null;
                }
            }

            // If we are on a svelte device, make sure an interactor is not currently
            // enabled; if it is, turn it off.
            if (!mEnableService && curInteractorStr != null) {
                if (!TextUtils.isEmpty(curInteractorStr)) {
                    if (DEBUG) Slog.d(TAG, "Svelte device; disabling interactor");
                    setCurInteractor(null, userHandle);
                    curInteractorStr = "";
                }
            }

            if (curRecognizer != null) {
                // If we already have at least a recognizer, then we probably want to
                // leave things as they are...  unless something has disappeared.
                IPackageManager pm = AppGlobals.getPackageManager();
                ServiceInfo interactorInfo = null;
                ServiceInfo recognizerInfo = null;
                ComponentName curInteractor = !TextUtils.isEmpty(curInteractorStr)
                        ? ComponentName.unflattenFromString(curInteractorStr) : null;
                try {
                    recognizerInfo = pm.getServiceInfo(curRecognizer,
                            PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
                    if (curInteractor != null) {
                        interactorInfo = pm.getServiceInfo(curInteractor,
                                PackageManager.MATCH_DIRECT_BOOT_AWARE
                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
                    }
                } catch (RemoteException e) {
                }
                // If the apps for the currently set components still exist, then all is okay.
                if (recognizerInfo != null && (curInteractor == null || interactorInfo != null)) {
                    if (DEBUG) Slog.d(TAG, "Current interactor/recognizer okay, done!");
                    return;
                }
                if (DEBUG) Slog.d(TAG, "Bad recognizer (" + recognizerInfo + ") or interactor ("
                        + interactorInfo + ")");
            }

            // Initializing settings, look for an interactor first (but only on non-svelte).
            if (curInteractorInfo == null && mEnableService) {
                curInteractorInfo = findAvailInteractor(userHandle, null);
            }

            if (curInteractorInfo != null) {
                // Eventually it will be an error to not specify this.
                setCurInteractor(new ComponentName(curInteractorInfo.getServiceInfo().packageName,
                        curInteractorInfo.getServiceInfo().name), userHandle);
                if (curInteractorInfo.getRecognitionService() != null) {
                    setCurRecognizer(
                            new ComponentName(curInteractorInfo.getServiceInfo().packageName,
                                    curInteractorInfo.getRecognitionService()), userHandle);
                    return;
                }
            }

            // No voice interactor, we'll just set up a simple recognizer.
            initSimpleRecognizer(curInteractorInfo, userHandle);
        }

        public void initSimpleRecognizer(VoiceInteractionServiceInfo curInteractorInfo,
                int userHandle) {
            ComponentName curRecognizer = findAvailRecognizer(null, userHandle);
            if (curRecognizer != null) {
                if (curInteractorInfo == null) {
                    setCurInteractor(null, userHandle);
                }
                setCurRecognizer(curRecognizer, userHandle);
            }
        }

        private boolean shouldEnableService(Context context) {
            // VoiceInteractionService should not be enabled on devices that have not declared the
            // recognition feature (including low-ram devices where notLowRam="true" takes effect),
            // unless the device's configuration has explicitly set the config flag for a fixed
            // voice interaction service.
            if (getForceVoiceInteractionServicePackage(context.getResources()) != null) {
                return true;
            }
            return context.getPackageManager()
                    .hasSystemFeature(PackageManager.FEATURE_VOICE_RECOGNIZERS);
        }

        private String getForceVoiceInteractionServicePackage(Resources res) {
            String interactorPackage =
                    res.getString(com.android.internal.R.string.config_forceVoiceInteractionServicePackage);
            return TextUtils.isEmpty(interactorPackage) ? null : interactorPackage;
        }

        public void systemRunning(boolean safeMode) {
            mSafeMode = safeMode;

            mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(),
                    UserHandle.ALL, true);
            new SettingsObserver(UiThread.getHandler());

            synchronized (this) {
                mCurUser = ActivityManager.getCurrentUser();
                switchImplementationIfNeededLocked(false);
            }
        }

        public void switchUser(int userHandle) {
            FgThread.getHandler().post(() -> {
                synchronized (this) {
                    mCurUser = userHandle;
                    mCurUserUnlocked = false;
                    switchImplementationIfNeededLocked(false);
                }
            });
        }

        void switchImplementationIfNeeded(boolean force) {
            synchronized (this) {
                switchImplementationIfNeededLocked(force);
            }
        }

        void switchImplementationIfNeededLocked(boolean force) {
            final TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            t.traceBegin("switchImplementation(" + mCurUser + ")");
            try {
                switchImplementationIfNeededNoTracingLocked(force);
            } finally {
                t.traceEnd();
            }
        }

        void switchImplementationIfNeededNoTracingLocked(boolean force) {
            if (!mSafeMode) {
                String curService = Settings.Secure.getStringForUser(
                        mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
                ComponentName serviceComponent = null;
                ServiceInfo serviceInfo = null;
                if (curService != null && !curService.isEmpty()) {
                    try {
                        serviceComponent = ComponentName.unflattenFromString(curService);
                        serviceInfo = AppGlobals.getPackageManager()
                                .getServiceInfo(serviceComponent, 0, mCurUser);
                    } catch (RuntimeException | RemoteException e) {
                        Slog.wtf(TAG, "Bad voice interaction service name " + curService, e);
                        serviceComponent = null;
                        serviceInfo = null;
                    }
                }

                final boolean hasComponent = serviceComponent != null && serviceInfo != null;

                if (mUserManager.isUserUnlockingOrUnlocked(mCurUser)) {
                    if (hasComponent) {
                        mShortcutServiceInternal.setShortcutHostPackage(TAG,
                                serviceComponent.getPackageName(), mCurUser);
                        mAtmInternal.setAllowAppSwitches(TAG,
                                serviceInfo.applicationInfo.uid, mCurUser);
                    } else {
                        mShortcutServiceInternal.setShortcutHostPackage(TAG, null, mCurUser);
                        mAtmInternal.setAllowAppSwitches(TAG, -1, mCurUser);
                    }
                }

                if (force || mImpl == null || mImpl.mUser != mCurUser
                        || !mImpl.mComponent.equals(serviceComponent)) {
                    unloadAllKeyphraseModels();
                    if (mImpl != null) {
                        mImpl.shutdownLocked();
                    }
                    if (hasComponent) {
                        setImplLocked(new VoiceInteractionManagerServiceImpl(mContext,
                                UiThread.getHandler(), this, mCurUser, serviceComponent));
                        mImpl.startLocked();
                    } else {
                        setImplLocked(null);
                    }
                }
            }
        }

        VoiceInteractionServiceInfo findAvailInteractor(int userHandle, String packageName) {
            List<ResolveInfo> available =
                    mContext.getPackageManager().queryIntentServicesAsUser(
                            new Intent(VoiceInteractionService.SERVICE_INTERFACE),
                            PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                    | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userHandle);
            int numAvailable = available.size();

            if (numAvailable == 0) {
                Slog.w(TAG, "no available voice interaction services found for user " + userHandle);
                return null;
            } else {
                // Find first system package.  We never want to allow third party services to
                // be automatically selected, because those require approval of the user.
                VoiceInteractionServiceInfo foundInfo = null;
                for (int i=0; i<numAvailable; i++) {
                    ServiceInfo cur = available.get(i).serviceInfo;
                    if ((cur.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
                        ComponentName comp = new ComponentName(cur.packageName, cur.name);
                        try {
                            VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo(
                                    mContext.getPackageManager(), comp, userHandle);
                            if (info.getParseError() == null) {
                                if (packageName == null || info.getServiceInfo().packageName.equals(
                                        packageName)) {
                                    if (foundInfo == null) {
                                        foundInfo = info;
                                    } else {
                                        Slog.w(TAG, "More than one voice interaction service, "
                                                + "picking first "
                                                + new ComponentName(
                                                        foundInfo.getServiceInfo().packageName,
                                                        foundInfo.getServiceInfo().name)
                                                + " over "
                                                + new ComponentName(cur.packageName, cur.name));
                                    }
                                }
                            } else {
                                Slog.w(TAG, "Bad interaction service " + comp + ": "
                                        + info.getParseError());
                            }
                        } catch (PackageManager.NameNotFoundException e) {
                            Slog.w(TAG, "Failure looking up interaction service " + comp);
                        }
                    }
                }

                return foundInfo;
            }
        }

        ComponentName getCurInteractor(int userHandle) {
            String curInteractor = Settings.Secure.getStringForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
            if (TextUtils.isEmpty(curInteractor)) {
                return null;
            }
            if (DEBUG) Slog.d(TAG, "getCurInteractor curInteractor=" + curInteractor
                    + " user=" + userHandle);
            return ComponentName.unflattenFromString(curInteractor);
        }

        void setCurInteractor(ComponentName comp, int userHandle) {
            Settings.Secure.putStringForUser(mContext.getContentResolver(),
                    Settings.Secure.VOICE_INTERACTION_SERVICE,
                    comp != null ? comp.flattenToShortString() : "", userHandle);
            if (DEBUG) Slog.d(TAG, "setCurInteractor comp=" + comp
                    + " user=" + userHandle);
        }

        ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
            List<ResolveInfo> available =
                    mContext.getPackageManager().queryIntentServicesAsUser(
                            new Intent(RecognitionService.SERVICE_INTERFACE),
                            PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
            int numAvailable = available.size();

            if (numAvailable == 0) {
                Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
                return null;
            } else {
                if (prefPackage != null) {
                    for (int i=0; i<numAvailable; i++) {
                        ServiceInfo serviceInfo = available.get(i).serviceInfo;
                        if (prefPackage.equals(serviceInfo.packageName)) {
                            return new ComponentName(serviceInfo.packageName, serviceInfo.name);
                        }
                    }
                }
                if (numAvailable > 1) {
                    Slog.w(TAG, "more than one voice recognition service found, picking first");
                }

                ServiceInfo serviceInfo = available.get(0).serviceInfo;
                return new ComponentName(serviceInfo.packageName, serviceInfo.name);
            }
        }

        ComponentName getCurRecognizer(int userHandle) {
            String curRecognizer = Settings.Secure.getStringForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle);
            if (TextUtils.isEmpty(curRecognizer)) {
                return null;
            }
            if (DEBUG) Slog.d(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
                    + " user=" + userHandle);
            return ComponentName.unflattenFromString(curRecognizer);
        }

        void setCurRecognizer(ComponentName comp, int userHandle) {
            Settings.Secure.putStringForUser(mContext.getContentResolver(),
                    Settings.Secure.VOICE_RECOGNITION_SERVICE,
                    comp != null ? comp.flattenToShortString() : "", userHandle);
            if (DEBUG) Slog.d(TAG, "setCurRecognizer comp=" + comp
                    + " user=" + userHandle);
        }

        ComponentName getCurAssistant(int userHandle) {
            String curAssistant = Settings.Secure.getStringForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.ASSISTANT, userHandle);
            if (TextUtils.isEmpty(curAssistant)) {
                return null;
            }
            if (DEBUG) Slog.d(TAG, "getCurAssistant curAssistant=" + curAssistant
                    + " user=" + userHandle);
            return ComponentName.unflattenFromString(curAssistant);
        }

        void resetCurAssistant(int userHandle) {
            Settings.Secure.putStringForUser(mContext.getContentResolver(),
                    Settings.Secure.ASSISTANT, null, userHandle);
        }

        @Override
        public void showSession(IVoiceInteractionService service, Bundle args, int flags) {
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);

                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.showSessionLocked(args, flags, null, null);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
                IVoiceInteractor interactor) {
            synchronized (this) {
                if (mImpl == null) {
                    throw new SecurityException(
                            "deliverNewSession without running voice interaction service");
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.deliverNewSessionLocked(token, session, interactor);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public boolean showSessionFromSession(IBinder token, Bundle sessionArgs, int flags) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "showSessionFromSession without running voice interaction service");
                    return false;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.showSessionLocked(sessionArgs, flags, null, null);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public boolean hideSessionFromSession(IBinder token) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "hideSessionFromSession without running voice interaction service");
                    return false;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.hideSessionLocked();
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "startVoiceActivity without running voice interaction service");
                    return ActivityManager.START_CANCELED;
                }
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
                            intent, resolvedType);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public int startAssistantActivity(IBinder token, Intent intent, String resolvedType) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "startAssistantActivity without running voice interaction service");
                    return ActivityManager.START_CANCELED;
                }
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.startAssistantActivityLocked(callingPid, callingUid, token,
                            intent, resolvedType);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void requestDirectActions(@NonNull IBinder token, int taskId,
                @NonNull IBinder assistToken, @Nullable RemoteCallback cancellationCallback,
                @NonNull RemoteCallback resultCallback) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "requestDirectActions without running voice interaction service");
                    resultCallback.sendResult(null);
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.requestDirectActionsLocked(token, taskId, assistToken,
                            cancellationCallback, resultCallback);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void performDirectAction(@NonNull IBinder token, @NonNull String actionId,
                @NonNull Bundle arguments, int taskId, IBinder assistToken,
                @Nullable RemoteCallback cancellationCallback,
                @NonNull RemoteCallback resultCallback) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "performDirectAction without running voice interaction service");
                    resultCallback.sendResult(null);
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.performDirectActionLocked(token, actionId, arguments, taskId,
                            assistToken, cancellationCallback, resultCallback);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void setKeepAwake(IBinder token, boolean keepAwake) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "setKeepAwake without running voice interaction service");
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.setKeepAwakeLocked(token, keepAwake);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void closeSystemDialogs(IBinder token) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "closeSystemDialogs without running voice interaction service");
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.closeSystemDialogsLocked(token);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void finish(IBinder token) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "finish without running voice interaction service");
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.finishLocked(token, false);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void setDisabledShowContext(int flags) {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "setDisabledShowContext without running voice interaction service");
                    return;
                }
                final int callingUid = Binder.getCallingUid();
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.setDisabledShowContextLocked(callingUid, flags);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public int getDisabledShowContext() {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "getDisabledShowContext without running voice interaction service");
                    return 0;
                }
                final int callingUid = Binder.getCallingUid();
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.getDisabledShowContextLocked(callingUid);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public int getUserDisabledShowContext() {
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG,
                            "getUserDisabledShowContext without running voice interaction service");
                    return 0;
                }
                final int callingUid = Binder.getCallingUid();
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.getUserDisabledShowContextLocked(callingUid);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        //----------------- Model management APIs --------------------------------//

        @Override
        public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);

            if (bcp47Locale == null) {
                throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
            }

            final int callingUid = UserHandle.getCallingUserId();
            final long caller = Binder.clearCallingIdentity();
            try {
                return mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        @Override
        public int updateKeyphraseSoundModel(KeyphraseSoundModel model) {
            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
            if (model == null) {
                throw new IllegalArgumentException("Model must not be null");
            }

            final long caller = Binder.clearCallingIdentity();
            try {
                if (mDbHelper.updateKeyphraseSoundModel(model)) {
                    synchronized (this) {
                        // Notify the voice interaction service of a change in sound models.
                        if (mImpl != null && mImpl.mService != null) {
                            mImpl.notifySoundModelsChangedLocked();
                        }
                    }
                    return SoundTriggerInternal.STATUS_OK;
                } else {
                    return SoundTriggerInternal.STATUS_ERROR;
                }
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        @Override
        public int deleteKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
            enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);

            if (bcp47Locale == null) {
                throw new IllegalArgumentException(
                        "Illegal argument(s) in deleteKeyphraseSoundModel");
            }

            final int callingUid = UserHandle.getCallingUserId();
            final long caller = Binder.clearCallingIdentity();
            boolean deleted = false;
            try {
                int unloadStatus = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
                if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
                    Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
                }
                deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
                return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
            } finally {
                if (deleted) {
                    synchronized (this) {
                        // Notify the voice interaction service of a change in sound models.
                        if (mImpl != null && mImpl.mService != null) {
                            mImpl.notifySoundModelsChangedLocked();
                        }
                        mLoadedKeyphraseIds.remove(keyphraseId);
                    }
                }
                Binder.restoreCallingIdentity(caller);
            }
        }

        //----------------- SoundTrigger APIs --------------------------------//
        @Override
        public boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
                String bcp47Locale) {
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);
            }

            if (bcp47Locale == null) {
                throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
            }

            final int callingUid = UserHandle.getCallingUserId();
            final long caller = Binder.clearCallingIdentity();
            try {
                KeyphraseSoundModel model =
                        mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
                return model != null;
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        @Override
        public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
            // Allow the call if this is the current voice interaction service.
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);

                final long caller = Binder.clearCallingIdentity();
                try {
                    return mSoundTriggerInternal.getModuleProperties();
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public int startRecognition(IVoiceInteractionService service, int keyphraseId,
                String bcp47Locale, IRecognitionStatusCallback callback,
                RecognitionConfig recognitionConfig) {
            // Allow the call if this is the current voice interaction service.
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);

                if (callback == null || recognitionConfig == null || bcp47Locale == null) {
                    throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
                }
            }

            int callingUid = UserHandle.getCallingUserId();
            final long caller = Binder.clearCallingIdentity();
            try {
                KeyphraseSoundModel soundModel =
                        mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
                if (soundModel == null
                        || soundModel.uuid == null
                        || soundModel.keyphrases == null) {
                    Slog.w(TAG, "No matching sound model found in startRecognition");
                    return SoundTriggerInternal.STATUS_ERROR;
                } else {
                    // Regardless of the status of the start recognition, we need to make sure
                    // that we unload this model if needed later.
                    synchronized (this) {
                        mLoadedKeyphraseIds.add(keyphraseId);
                    }
                    return mSoundTriggerInternal.startRecognition(
                            keyphraseId, soundModel, callback, recognitionConfig);
                }
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        @Override
        public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
                IRecognitionStatusCallback callback) {
            // Allow the call if this is the current voice interaction service.
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);
            }

            final long caller = Binder.clearCallingIdentity();
            try {
                return mSoundTriggerInternal.stopRecognition(keyphraseId, callback);
            } finally {
                Binder.restoreCallingIdentity(caller);
            }
        }

        private synchronized void unloadAllKeyphraseModels() {
            for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) {
                final long caller = Binder.clearCallingIdentity();
                try {
                    int status = mSoundTriggerInternal.unloadKeyphraseModel(
                            mLoadedKeyphraseIds.valueAt(i));
                    if (status != SoundTriggerInternal.STATUS_OK) {
                        Slog.w(TAG, "Failed to unload keyphrase " + mLoadedKeyphraseIds.valueAt(i)
                                + ":" + status);
                    }
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
            mLoadedKeyphraseIds.clear();
        }

        @Override
        public ComponentName getActiveServiceComponentName() {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                return mImpl != null ? mImpl.mComponent : null;
            }
        }

        @Override
        public boolean showSessionForActiveService(Bundle args, int sourceFlags,
                IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "showSessionForActiveService without running voice interaction"
                            + "service");
                    return false;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    return mImpl.showSessionLocked(args,
                            sourceFlags
                                    | VoiceInteractionSession.SHOW_WITH_ASSIST
                                    | VoiceInteractionSession.SHOW_WITH_SCREENSHOT,
                            showCallback, activityToken);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void hideCurrentSession() throws RemoteException {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                if (mImpl == null) {
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
                        try {
                            mImpl.mActiveSession.mSession.closeSystemDialogs();
                        } catch (RemoteException e) {
                            Log.w(TAG, "Failed to call closeSystemDialogs", e);
                        }
                    }
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void launchVoiceAssistFromKeyguard() {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                if (mImpl == null) {
                    Slog.w(TAG, "launchVoiceAssistFromKeyguard without running voice interaction"
                            + "service");
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.launchVoiceAssistFromKeyguard();
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public boolean isSessionRunning() {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                return mImpl != null && mImpl.mActiveSession != null;
            }
        }

        @Override
        public boolean activeServiceSupportsAssist() {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                return mImpl != null && mImpl.mInfo != null && mImpl.mInfo.getSupportsAssist();
            }
        }

        @Override
        public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                return mImpl != null && mImpl.mInfo != null
                        && mImpl.mInfo.getSupportsLaunchFromKeyguard();
            }
        }

        @Override
        public void onLockscreenShown() {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                if (mImpl == null) {
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
                        try {
                            mImpl.mActiveSession.mSession.onLockscreenShown();
                        } catch (RemoteException e) {
                            Log.w(TAG, "Failed to call onLockscreenShown", e);
                        }
                    }
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        @Override
        public void registerVoiceInteractionSessionListener(
                IVoiceInteractionSessionListener listener) {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                mVoiceInteractionSessionListeners.register(listener);
            }
        }

        @Override
        public void getActiveServiceSupportedActions(List<String> voiceActions,
                IVoiceActionCheckCallback callback) {
            enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
            synchronized (this) {
                if (mImpl == null) {
                    try {
                        callback.onComplete(null);
                    } catch (RemoteException e) {
                    }
                    return;
                }
                final long caller = Binder.clearCallingIdentity();
                try {
                    mImpl.getActiveServiceSupportedActions(voiceActions, callback);
                } finally {
                    Binder.restoreCallingIdentity(caller);
                }
            }
        }

        public void onSessionShown() {
            synchronized (this) {
                final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                for (int i = 0; i < size; ++i) {
                    final IVoiceInteractionSessionListener listener =
                            mVoiceInteractionSessionListeners.getBroadcastItem(i);
                    try {
                        listener.onVoiceSessionShown();
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Error delivering voice interaction open event.", e);
                    }
                }
                mVoiceInteractionSessionListeners.finishBroadcast();
            }
        }

        public void onSessionHidden() {
            synchronized (this) {
                final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                for (int i = 0; i < size; ++i) {
                    final IVoiceInteractionSessionListener listener =
                            mVoiceInteractionSessionListeners.getBroadcastItem(i);
                    try {
                        listener.onVoiceSessionHidden();

                    } catch (RemoteException e) {
                        Slog.e(TAG, "Error delivering voice interaction closed event.", e);
                    }
                }
                mVoiceInteractionSessionListeners.finishBroadcast();
            }
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
            synchronized (this) {
                pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
                pw.println("  mEnableService: " + mEnableService);
                if (mImpl == null) {
                    pw.println("  (No active implementation)");
                    return;
                }
                mImpl.dumpLocked(fd, pw, args);
            }
            mSoundTriggerInternal.dump(fd, pw, args);
        }

        @Override
        public void setUiHints(IVoiceInteractionService service, Bundle hints) {
            synchronized (this) {
                enforceIsCurrentVoiceInteractionService(service);

                final int size = mVoiceInteractionSessionListeners.beginBroadcast();
                for (int i = 0; i < size; ++i) {
                    final IVoiceInteractionSessionListener listener =
                            mVoiceInteractionSessionListeners.getBroadcastItem(i);
                    try {
                        listener.onSetUiHints(hints);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Error delivering UI hints.", e);
                    }
                }
                mVoiceInteractionSessionListeners.finishBroadcast();
            }
        }

        private void enforceCallingPermission(String permission) {
            if (mContext.checkCallingOrSelfPermission(permission)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("Caller does not hold the permission " + permission);
            }
        }

        private void enforceIsCurrentVoiceInteractionService(IVoiceInteractionService service) {
            if (mImpl == null || mImpl.mService == null
                    || service.asBinder() != mImpl.mService.asBinder()) {
                throw new
                    SecurityException("Caller is not the current voice interaction service");
            }
        }

        private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
            mImpl = impl;
            mAtmInternal.notifyActiveVoiceInteractionServiceChanged(
                    getActiveServiceComponentName());
        }

        class RoleObserver implements OnRoleHoldersChangedListener {
            private PackageManager mPm = mContext.getPackageManager();
            private RoleManager mRm = mContext.getSystemService(RoleManager.class);

            RoleObserver(@NonNull @CallbackExecutor Executor executor) {
                mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
                // Sync only if assistant role has been initialized.
                if (mRm.isRoleAvailable(RoleManager.ROLE_ASSISTANT)) {
                    UserHandle currentUser = UserHandle.of(LocalServices.getService(
                            ActivityManagerInternal.class).getCurrentUserId());
                    onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
                }
            }

            private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
                ResolveInfo resolveInfo = mPm.resolveServiceAsUser(
                        new Intent(RecognitionService.SERVICE_INTERFACE),
                        PackageManager.GET_META_DATA, user.getIdentifier());

                if (resolveInfo == null || resolveInfo.serviceInfo == null) {
                    Log.w(TAG, "Unable to resolve default voice recognition service.");
                    return "";
                }

                return new ComponentName(resolveInfo.serviceInfo.packageName,
                        resolveInfo.serviceInfo.name).flattenToShortString();
            }

            /**
             * Convert the assistant-role holder into settings. The rest of the system uses the
             * settings.
             *
             * @param roleName the name of the role whose holders are changed
             * @param user the user for this role holder change
             */
            @Override
            public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
                if (!roleName.equals(RoleManager.ROLE_ASSISTANT)) {
                    return;
                }

                List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user);

                int userId = user.getIdentifier();
                if (roleHolders.isEmpty()) {
                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
                            Settings.Secure.ASSISTANT, "", userId);
                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
                            Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
                    Settings.Secure.putStringForUser(getContext().getContentResolver(),
                            Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user),
                            userId);
                } else {
                    // Assistant is singleton role
                    String pkg = roleHolders.get(0);

                    // Try to set role holder as VoiceInteractionService
                    List<ResolveInfo> services = mPm.queryIntentServicesAsUser(
                            new Intent(VoiceInteractionService.SERVICE_INTERFACE).setPackage(pkg),
                            PackageManager.GET_META_DATA
                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);

                    for (ResolveInfo resolveInfo : services) {
                        ServiceInfo serviceInfo = resolveInfo.serviceInfo;

                        VoiceInteractionServiceInfo voiceInteractionServiceInfo =
                                new VoiceInteractionServiceInfo(mPm, serviceInfo);
                        if (!voiceInteractionServiceInfo.getSupportsAssist()) {
                            continue;
                        }

                        String serviceComponentName = serviceInfo.getComponentName()
                                .flattenToShortString();

                        String serviceRecognizerName = new ComponentName(pkg,
                                voiceInteractionServiceInfo.getRecognitionService())
                                .flattenToShortString();

                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.ASSISTANT, serviceComponentName, userId);
                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName,
                                userId);
                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName,
                                userId);

                        return;
                    }

                    // If no service could be found try to set assist activity
                    final List<ResolveInfo> activities = mPm.queryIntentActivitiesAsUser(
                            new Intent(Intent.ACTION_ASSIST).setPackage(pkg),
                            PackageManager.MATCH_DEFAULT_ONLY
                                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);

                    for (ResolveInfo resolveInfo : activities) {
                        ActivityInfo activityInfo = resolveInfo.activityInfo;

                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.ASSISTANT,
                                activityInfo.getComponentName().flattenToShortString(), userId);
                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.VOICE_INTERACTION_SERVICE, "", userId);
                        Settings.Secure.putStringForUser(getContext().getContentResolver(),
                                Settings.Secure.VOICE_RECOGNITION_SERVICE,
                                getDefaultRecognizer(user), userId);
                        return;
                    }
                }
            }
        }

        class SettingsObserver extends ContentObserver {
            SettingsObserver(Handler handler) {
                super(handler);
                ContentResolver resolver = mContext.getContentResolver();
                resolver.registerContentObserver(Settings.Secure.getUriFor(
                        Settings.Secure.VOICE_INTERACTION_SERVICE), false, this,
                        UserHandle.USER_ALL);
            }

            @Override public void onChange(boolean selfChange) {
                synchronized (VoiceInteractionManagerServiceStub.this) {
                    switchImplementationIfNeededLocked(false);
                }
            }
        }

        PackageMonitor mPackageMonitor = new PackageMonitor() {
            @Override
            public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
                if (DEBUG) Slog.d(TAG, "onHandleForceStop uid=" + uid + " doit=" + doit);

                int userHandle = UserHandle.getUserId(uid);
                ComponentName curInteractor = getCurInteractor(userHandle);
                ComponentName curRecognizer = getCurRecognizer(userHandle);
                boolean hitInt = false;
                boolean hitRec = false;
                for (String pkg : packages) {
                    if (curInteractor != null && pkg.equals(curInteractor.getPackageName())) {
                        hitInt = true;
                        break;
                    } else if (curRecognizer != null
                            && pkg.equals(curRecognizer.getPackageName())) {
                        hitRec = true;
                        break;
                    }
                }
                if (hitInt && doit) {
                    // The user is force stopping our current interactor.
                    // Clear the current settings and restore default state.
                    synchronized (VoiceInteractionManagerServiceStub.this) {
                        Slog.i(TAG, "Force stopping current voice interactor: "
                                + getCurInteractor(userHandle));
                        unloadAllKeyphraseModels();
                        if (mImpl != null) {
                            mImpl.shutdownLocked();
                            setImplLocked(null);
                        }

                        setCurInteractor(null, userHandle);
                        setCurRecognizer(null, userHandle);
                        resetCurAssistant(userHandle);
                        initForUser(userHandle);
                        switchImplementationIfNeededLocked(true);

                        Context context = getContext();
                        context.getSystemService(RoleManager.class).clearRoleHoldersAsUser(
                                RoleManager.ROLE_ASSISTANT, 0, UserHandle.of(userHandle),
                                context.getMainExecutor(), successful -> {
                                    if (!successful) {
                                        Slog.e(TAG,
                                                "Failed to clear default assistant for force stop");
                                    }
                                });
                    }
                } else if (hitRec && doit) {
                    // We are just force-stopping the current recognizer, which is not
                    // also the current interactor.
                    synchronized (VoiceInteractionManagerServiceStub.this) {
                        Slog.i(TAG, "Force stopping current voice recognizer: "
                                + getCurRecognizer(userHandle));
                        initSimpleRecognizer(null, userHandle);
                    }
                }
                return hitInt || hitRec;
            }

            @Override
            public void onHandleUserStop(Intent intent, int userHandle) {
            }

            @Override
            public void onPackageModified(String pkgName) {
                // If the package modified is not in the current user, then don't bother making
                // any changes as we are going to do any initialization needed when we switch users.
                if (mCurUser != getChangingUserId()) {
                    return;
                }
                // Package getting updated will be handled by {@link #onSomePackagesChanged}.
                if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) {
                    return;
                }
                final ComponentName curInteractor = getCurInteractor(mCurUser);
                if (curInteractor == null) {
                    final VoiceInteractionServiceInfo availInteractorInfo
                            = findAvailInteractor(mCurUser, pkgName);
                    if (availInteractorInfo != null) {
                        final ComponentName availInteractor = new ComponentName(
                                availInteractorInfo.getServiceInfo().packageName,
                                availInteractorInfo.getServiceInfo().name);
                        setCurInteractor(availInteractor, mCurUser);
                        if (getCurRecognizer(mCurUser) == null &&
                                availInteractorInfo.getRecognitionService() != null) {
                            setCurRecognizer(new ComponentName(
                                    availInteractorInfo.getServiceInfo().packageName,
                                    availInteractorInfo.getRecognitionService()), mCurUser);
                        }
                    }
                } else {
                    if (didSomePackagesChange()) {
                        // Package is changed
                        if (curInteractor != null && pkgName.equals(
                                curInteractor.getPackageName())) {
                            switchImplementationIfNeeded(true);
                        }
                    } else {
                        // Only some components are changed
                        if (curInteractor != null
                                && isComponentModified(curInteractor.getClassName())) {
                            switchImplementationIfNeeded(true);
                        }
                    }
                }
            }

            @Override
            public void onSomePackagesChanged() {
                int userHandle = getChangingUserId();
                if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);

                synchronized (VoiceInteractionManagerServiceStub.this) {
                    ComponentName curInteractor = getCurInteractor(userHandle);
                    ComponentName curRecognizer = getCurRecognizer(userHandle);
                    ComponentName curAssistant = getCurAssistant(userHandle);
                    if (curRecognizer == null) {
                        // Could a new recognizer appear when we don't have one pre-installed?
                        if (anyPackagesAppearing()) {
                            curRecognizer = findAvailRecognizer(null, userHandle);
                            if (curRecognizer != null) {
                                setCurRecognizer(curRecognizer, userHandle);
                            }
                        }
                        return;
                    }

                    if (curInteractor != null) {
                        int change = isPackageDisappearing(curInteractor.getPackageName());
                        if (change == PACKAGE_PERMANENT_CHANGE) {
                            // The currently set interactor is permanently gone; fall back to
                            // the default config.
                            setCurInteractor(null, userHandle);
                            setCurRecognizer(null, userHandle);
                            resetCurAssistant(userHandle);
                            initForUser(userHandle);
                            return;
                        }

                        change = isPackageAppearing(curInteractor.getPackageName());
                        if (change != PACKAGE_UNCHANGED) {
                            // If current interactor is now appearing, for any reason, then
                            // restart our connection with it.
                            if (mImpl != null && curInteractor.getPackageName().equals(
                                    mImpl.mComponent.getPackageName())) {
                                switchImplementationIfNeededLocked(true);
                            }
                        }
                        return;
                    }

                    if (curAssistant != null) {
                        int change = isPackageDisappearing(curAssistant.getPackageName());
                        if (change == PACKAGE_PERMANENT_CHANGE) {
                            // If the currently set assistant is being removed, then we should
                            // reset back to the default state (which is probably that we prefer
                            // to have the default full voice interactor enabled).
                            setCurInteractor(null, userHandle);
                            setCurRecognizer(null, userHandle);
                            resetCurAssistant(userHandle);
                            initForUser(userHandle);
                            return;
                        }
                    }

                    // There is no interactor, so just deal with a simple recognizer.
                    int change = isPackageDisappearing(curRecognizer.getPackageName());
                    if (change == PACKAGE_PERMANENT_CHANGE
                            || change == PACKAGE_TEMPORARY_CHANGE) {
                        setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);

                    } else if (isPackageModified(curRecognizer.getPackageName())) {
                        setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(),
                                userHandle), userHandle);
                    }
                }
            }
        };
    }
}
