191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn/*
291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Copyright (C) 2014 The Android Open Source Project
391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * you may not use this file except in compliance with the License.
691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * You may obtain a copy of the License at
791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
1091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * See the License for the specific language governing permissions and
1491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * limitations under the License.
1591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */
1691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
1791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpackage com.android.server.voiceinteraction;
1891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
1918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.Manifest;
2091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.app.ActivityManager;
21a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.app.AppGlobals;
2291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.ComponentName;
2391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.ContentResolver;
2491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Context;
2591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Intent;
26a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.content.pm.ApplicationInfo;
27a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.content.pm.IPackageManager;
2818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.content.pm.PackageManager;
29a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.content.pm.ResolveInfo;
30a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.content.pm.ServiceInfo;
3191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.database.ContentObserver;
32055897208d659e9734a82def88be4a806ff55448Sandeep Siddharthaimport android.hardware.soundtrigger.IRecognitionStatusCallback;
33055897208d659e9734a82def88be4a806ff55448Sandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
34055897208d659e9734a82def88be4a806ff55448Sandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
35055897208d659e9734a82def88be4a806ff55448Sandeep Siddharthaimport android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
3691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Binder;
3718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.os.Bundle;
3891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Handler;
3918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.os.IBinder;
40c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackbornimport android.os.Parcel;
41c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackbornimport android.os.RemoteException;
42d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackbornimport android.os.SystemProperties;
4391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.UserHandle;
4491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.provider.Settings;
4591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.service.voice.IVoiceInteractionService;
4691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.service.voice.IVoiceInteractionSession;
47a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.service.voice.VoiceInteractionService;
48a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.service.voice.VoiceInteractionServiceInfo;
49a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.speech.RecognitionService;
50a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport android.text.TextUtils;
5191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.util.Slog;
52d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep
5391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractionManagerService;
5491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractor;
5591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.content.PackageMonitor;
5691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.os.BackgroundThread;
5791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.server.SystemService;
5891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.server.UiThread;
5991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
6091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport java.io.FileDescriptor;
6191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport java.io.PrintWriter;
62a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackbornimport java.util.List;
6391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
6491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn/**
6591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * SystemService that publishes an IVoiceInteractionManagerService.
6691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */
6791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpublic class VoiceInteractionManagerService extends SystemService {
6891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final String TAG = "VoiceInteractionManagerService";
69a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn    static final boolean DEBUG = false;
7091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
7191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final Context mContext;
7291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final ContentResolver mResolver;
732883ba69751de69811a38f086ecbe4c2032ca87dSandeep Siddhartha    final DatabaseHelper mDbHelper;
74055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha    final SoundTriggerHelper mSoundTriggerHelper;
7591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
7691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public VoiceInteractionManagerService(Context context) {
7791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        super(context);
7891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mContext = context;
7991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mResolver = context.getContentResolver();
802883ba69751de69811a38f086ecbe4c2032ca87dSandeep Siddhartha        mDbHelper = new DatabaseHelper(context);
81efe0f9c7f2bdc10cfd28c186e68676e27b6944a1Sandeep Siddhartha        mSoundTriggerHelper = new SoundTriggerHelper(context);
8291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
8391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
8491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    @Override
8591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public void onStart() {
8691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        publishBinderService(Context.VOICE_INTERACTION_MANAGER_SERVICE, mServiceStub);
8791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
8891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
8991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    @Override
9091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public void onBootPhase(int phase) {
9191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
9291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mServiceStub.systemRunning(isSafeMode());
9391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
9491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
9591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
9691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    @Override
97a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn    public void onStartUser(int userHandle) {
98a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        mServiceStub.initForUser(userHandle);
99a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn    }
100a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
101a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn    @Override
10291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public void onSwitchUser(int userHandle) {
10391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mServiceStub.switchUser(userHandle);
10491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
10591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
10691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    // implementation entry point and binder service
10791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    private final VoiceInteractionManagerServiceStub mServiceStub
10891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            = new VoiceInteractionManagerServiceStub();
10991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
11091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
11191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
11291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        VoiceInteractionManagerServiceImpl mImpl;
11391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
11491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        private boolean mSafeMode;
11591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        private int mCurUser;
11691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
117c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        @Override
118c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
119c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                throws RemoteException {
120c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            try {
121c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                return super.onTransact(code, data, reply, flags);
122c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            } catch (RuntimeException e) {
123c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                // The activity manager only throws security exceptions, so let's
124c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                // log all others.
125c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                if (!(e instanceof SecurityException)) {
126c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
127c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
128c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                throw e;
129c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            }
130c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        }
131c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn
132a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        public void initForUser(int userHandle) {
133a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
13416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn            String curInteractorStr = Settings.Secure.getStringForUser(
13516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    mContext.getContentResolver(),
13616ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
137a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            ComponentName curRecognizer = getCurRecognizer(userHandle);
13816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn            VoiceInteractionServiceInfo curInteractorInfo = null;
139c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            if (curInteractorStr == null && curRecognizer != null
140c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                    && !ActivityManager.isLowRamDeviceStatic()) {
14116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                // If there is no interactor setting, that means we are upgrading
14216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                // from an older platform version.  If the current recognizer is not
14316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                // set or matches the preferred recognizer, then we want to upgrade
14416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                // the user to have the default voice interaction service enabled.
145c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                // Note that we don't do this for low-RAM devices, since we aren't
146c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                // supporting voice interaction services there.
14716ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                curInteractorInfo = findAvailInteractor(userHandle, curRecognizer);
14816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                if (curInteractorInfo != null) {
14916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    // Looks good!  We'll apply this one.  To make it happen, we clear the
15016ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    // recognizer so that we don't think we have anything set and will
15116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    // re-apply the settings.
15216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    curRecognizer = null;
15316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                }
15416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn            }
15516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn
156c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            // If we are on a svelte device, make sure an interactor is not currently
157c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            // enabled; if it is, turn it off.
158c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            if (ActivityManager.isLowRamDeviceStatic() && curInteractorStr != null) {
159c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                if (!TextUtils.isEmpty(curInteractorStr)) {
160c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                    setCurInteractor(null, userHandle);
161c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                    curInteractorStr = "";
162c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn                }
163c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            }
164c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn
165a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (curRecognizer != null) {
166a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // If we already have at least a recognizer, then we probably want to
167a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // leave things as they are...  unless something has disappeared.
168a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                IPackageManager pm = AppGlobals.getPackageManager();
169a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                ServiceInfo interactorInfo = null;
170a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                ServiceInfo recognizerInfo = null;
17116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                ComponentName curInteractor = !TextUtils.isEmpty(curInteractorStr)
17216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        ? ComponentName.unflattenFromString(curInteractorStr) : null;
173a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                try {
174a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    recognizerInfo = pm.getServiceInfo(curRecognizer, 0, userHandle);
175a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    if (curInteractor != null) {
176a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        interactorInfo = pm.getServiceInfo(curInteractor, 0, userHandle);
177a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
178a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                } catch (RemoteException e) {
179a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
180a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // If the apps for the currently set components still exist, then all is okay.
181a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (recognizerInfo != null && (curInteractor == null || interactorInfo != null)) {
182a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    return;
183a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
184a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
185a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
186c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            // Initializing settings, look for an interactor first (but only on non-svelte).
187c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn            if (curInteractorInfo == null && !ActivityManager.isLowRamDeviceStatic()) {
18816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                curInteractorInfo = findAvailInteractor(userHandle, null);
18916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn            }
190c0e4aaad1ecd5df2608f10a644f3d8f60056d94cDianne Hackborn
19116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn            if (curInteractorInfo != null) {
19216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                // Eventually it will be an error to not specify this.
19316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                setCurInteractor(new ComponentName(curInteractorInfo.getServiceInfo().packageName,
19416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        curInteractorInfo.getServiceInfo().name), userHandle);
19516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                if (curInteractorInfo.getRecognitionService() != null) {
19616ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    setCurRecognizer(
19716ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            new ComponentName(curInteractorInfo.getServiceInfo().packageName,
19816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                    curInteractorInfo.getRecognitionService()), userHandle);
19916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    return;
200a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
201a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
202a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
203a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            // No voice interactor, we'll just set up a simple recognizer.
204a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            curRecognizer = findAvailRecognizer(null, userHandle);
205a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (curRecognizer != null) {
20616ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                if (curInteractorInfo == null) {
20716ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                    setCurInteractor(null, userHandle);
20816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                }
209a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                setCurRecognizer(curRecognizer, userHandle);
210a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
211a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
212a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
21391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void systemRunning(boolean safeMode) {
21491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mSafeMode = safeMode;
21591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
21691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(),
21791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    UserHandle.ALL, true);
21891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            new SettingsObserver(UiThread.getHandler());
21991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
22091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            synchronized (this) {
22191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mCurUser = ActivityManager.getCurrentUser();
222c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                switchImplementationIfNeededLocked(false);
22391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
22491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
22591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
22691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void switchUser(int userHandle) {
22791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            synchronized (this) {
22891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mCurUser = userHandle;
229c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                switchImplementationIfNeededLocked(false);
23091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
23191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
23291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
233c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        void switchImplementationIfNeededLocked(boolean force) {
23491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            if (!mSafeMode) {
23591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                String curService = Settings.Secure.getStringForUser(
23691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
23791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                ComponentName serviceComponent = null;
23891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                if (curService != null && !curService.isEmpty()) {
23991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    try {
24091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        serviceComponent = ComponentName.unflattenFromString(curService);
24191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    } catch (RuntimeException e) {
24291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        Slog.wtf(TAG, "Bad voice interaction service name " + curService, e);
24391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        serviceComponent = null;
24491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    }
24591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
246c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                if (force || mImpl == null || mImpl.mUser != mCurUser
24791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        || !mImpl.mComponent.equals(serviceComponent)) {
2485e33fb057c20b84418d96574abe861e9d05956ebSandeep Siddhartha                    mSoundTriggerHelper.stopAllRecognitions();
24991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (mImpl != null) {
25091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        mImpl.shutdownLocked();
25191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    }
25291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (serviceComponent != null) {
25391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        mImpl = new VoiceInteractionManagerServiceImpl(mContext,
25491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                                UiThread.getHandler(), this, mCurUser, serviceComponent);
25591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        mImpl.startLocked();
25691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    } else {
25791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        mImpl = null;
25891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    }
25991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
26091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
26191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
26291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
26316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn        VoiceInteractionServiceInfo findAvailInteractor(int userHandle, ComponentName recognizer) {
264a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            List<ResolveInfo> available =
265a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    mContext.getPackageManager().queryIntentServicesAsUser(
266a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            new Intent(VoiceInteractionService.SERVICE_INTERFACE), 0, userHandle);
267a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            int numAvailable = available.size();
268a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
269a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (numAvailable == 0) {
270a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                Slog.w(TAG, "no available voice interaction services found for user " + userHandle);
271a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                return null;
272a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            } else {
273a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // Find first system package.  We never want to allow third party services to
274a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // be automatically selected, because those require approval of the user.
27516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                VoiceInteractionServiceInfo foundInfo = null;
276a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                for (int i=0; i<numAvailable; i++) {
277a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    ServiceInfo cur = available.get(i).serviceInfo;
278a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    if ((cur.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
27916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        ComponentName comp = new ComponentName(cur.packageName, cur.name);
28016ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        try {
28116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo(
28216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                    mContext.getPackageManager(), comp, userHandle);
28316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            if (info.getParseError() == null) {
28416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                if (recognizer == null || info.getServiceInfo().packageName.equals(
28516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                        recognizer.getPackageName())) {
28616ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                    if (foundInfo == null) {
28716ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                        foundInfo = info;
28816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                    } else {
28916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                        Slog.w(TAG, "More than one voice interaction service, "
29016ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                + "picking first "
29116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                + new ComponentName(
29216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                        foundInfo.getServiceInfo().packageName,
29316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                        foundInfo.getServiceInfo().name)
29416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                + " over "
29516ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                                + new ComponentName(cur.packageName, cur.name));
29616ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                    }
29716ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                }
29816ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            } else {
29916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                Slog.w(TAG, "Bad interaction service " + comp + ": "
30016ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                                        + info.getParseError());
30116ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            }
30216ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        } catch (PackageManager.NameNotFoundException e) {
30316ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                            Slog.w(TAG, "Failure looking up interaction service " + comp);
30416ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                        } catch (RemoteException e) {
305a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        }
306a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
307a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
308a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
30916ec0808b5c19f8f33cdacb7b2e444eebfae7d21Dianne Hackborn                return foundInfo;
310a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
311a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
312a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
313a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        ComponentName getCurInteractor(int userHandle) {
314a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            String curInteractor = Settings.Secure.getStringForUser(
315a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    mContext.getContentResolver(),
316a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
317a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (TextUtils.isEmpty(curInteractor)) {
318a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                return null;
319a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
320a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (DEBUG) Slog.i(TAG, "getCurInteractor curInteractor=" + curInteractor
321a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    + " user=" + userHandle);
322a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            return ComponentName.unflattenFromString(curInteractor);
323a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
324a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
325a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        void setCurInteractor(ComponentName comp, int userHandle) {
326a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            Settings.Secure.putStringForUser(mContext.getContentResolver(),
327a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    Settings.Secure.VOICE_INTERACTION_SERVICE,
328a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    comp != null ? comp.flattenToShortString() : "", userHandle);
329a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (DEBUG) Slog.i(TAG, "setCurInteractor comp=" + comp
330a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    + " user=" + userHandle);
331a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
332a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
333a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
334a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            List<ResolveInfo> available =
335a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    mContext.getPackageManager().queryIntentServicesAsUser(
336a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle);
337a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            int numAvailable = available.size();
338a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
339a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (numAvailable == 0) {
340a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
341a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                return null;
342a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            } else {
343a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (prefPackage != null) {
344a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    for (int i=0; i<numAvailable; i++) {
345a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        ServiceInfo serviceInfo = available.get(i).serviceInfo;
346a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        if (prefPackage.equals(serviceInfo.packageName)) {
347a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            return new ComponentName(serviceInfo.packageName, serviceInfo.name);
348a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        }
349a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
350a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
351a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (numAvailable > 1) {
352a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    Slog.w(TAG, "more than one voice recognition service found, picking first");
353a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
354a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
355a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                ServiceInfo serviceInfo = available.get(0).serviceInfo;
356a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                return new ComponentName(serviceInfo.packageName, serviceInfo.name);
357a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
358a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
359a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
360a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        ComponentName getCurRecognizer(int userHandle) {
361a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            String curRecognizer = Settings.Secure.getStringForUser(
362a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    mContext.getContentResolver(),
363a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle);
364a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (TextUtils.isEmpty(curRecognizer)) {
365a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                return null;
366a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            }
367a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (DEBUG) Slog.i(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
368a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    + " user=" + userHandle);
369a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            return ComponentName.unflattenFromString(curRecognizer);
370a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
371a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
372a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        void setCurRecognizer(ComponentName comp, int userHandle) {
373a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            Settings.Secure.putStringForUser(mContext.getContentResolver(),
374a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    Settings.Secure.VOICE_RECOGNITION_SERVICE,
375a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    comp != null ? comp.flattenToShortString() : "", userHandle);
376a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            if (DEBUG) Slog.i(TAG, "setCurRecognizer comp=" + comp
377a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    + " user=" + userHandle);
378a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn        }
379a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
38091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
381c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        public void startSession(IVoiceInteractionService service, Bundle args) {
38291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            synchronized (this) {
383c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                if (mImpl == null || mImpl.mService == null
384c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                        || service.asBinder() != mImpl.mService.asBinder()) {
38591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    throw new SecurityException(
38691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            "Caller is not the current voice interaction service");
38791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
38891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                final int callingPid = Binder.getCallingPid();
38991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                final int callingUid = Binder.getCallingUid();
39091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                final long caller = Binder.clearCallingIdentity();
39191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                try {
392c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    mImpl.startSessionLocked(callingPid, callingUid, args);
39391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                } finally {
39491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    Binder.restoreCallingIdentity(caller);
39591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
39691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
39791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
39891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
39991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
400c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
40118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                IVoiceInteractor interactor) {
40218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            synchronized (this) {
40318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                if (mImpl == null) {
404c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    throw new SecurityException(
405c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                            "deliverNewSession without running voice interaction service");
40618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                }
40718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                final int callingPid = Binder.getCallingPid();
40818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                final int callingUid = Binder.getCallingUid();
40918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                final long caller = Binder.clearCallingIdentity();
41018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                try {
41118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    return mImpl.deliverNewSessionLocked(callingPid, callingUid, token, session,
41218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            interactor);
41318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                } finally {
41418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    Binder.restoreCallingIdentity(caller);
41518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                }
41618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            }
417c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        }
41818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
419c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        @Override
420c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
421c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            synchronized (this) {
422c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                if (mImpl == null) {
423c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    Slog.w(TAG, "startVoiceActivity without running voice interaction service");
424c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    return ActivityManager.START_CANCELED;
425c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
426c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final int callingPid = Binder.getCallingPid();
427c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final int callingUid = Binder.getCallingUid();
428c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final long caller = Binder.clearCallingIdentity();
429d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackborn                if (!SystemProperties.getBoolean("persist.test.voice_interaction", false)) {
430d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackborn                    throw new SecurityException("Voice interaction not supported");
431d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackborn                }
432c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                try {
433c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
434c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                            intent, resolvedType);
435c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                } finally {
436c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    Binder.restoreCallingIdentity(caller);
437c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
438c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            }
439c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        }
440c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn
441c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        @Override
442c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn        public void finish(IBinder token) {
443c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            synchronized (this) {
444c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                if (mImpl == null) {
445c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    Slog.w(TAG, "finish without running voice interaction service");
446c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    return;
447c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
448c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final int callingPid = Binder.getCallingPid();
449c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final int callingUid = Binder.getCallingUid();
450c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                final long caller = Binder.clearCallingIdentity();
451c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                try {
452c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    mImpl.finishLocked(callingPid, callingUid, token);
453c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                } finally {
454c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    Binder.restoreCallingIdentity(caller);
455c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
456c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn            }
45718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
45818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
459055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        //----------------- Model management APIs --------------------------------//
460055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
46118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        @Override
4628cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha        public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
463d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep            synchronized (this) {
464452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
465452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        != PackageManager.PERMISSION_GRANTED) {
466452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    throw new SecurityException("Caller does not hold the permission "
467452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
468d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                }
469f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            }
470d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep
4718cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            if (bcp47Locale == null) {
4728cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
4738cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            }
4748cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha
4758cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            final int callingUid = UserHandle.getCallingUserId();
476f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
477f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            try {
4788cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                return mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
479f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            } finally {
480f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
481d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep            }
482d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep        }
483d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep
484d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep        @Override
485d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep        public int updateKeyphraseSoundModel(KeyphraseSoundModel model) {
486d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep            synchronized (this) {
487d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
488d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                        != PackageManager.PERMISSION_GRANTED) {
489d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                    throw new SecurityException("Caller does not hold the permission "
490d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
491d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                }
492f8cf71d753b86895f987f682c80491aa2967e0c2Sandeep Siddhartha                if (model == null) {
493f8cf71d753b86895f987f682c80491aa2967e0c2Sandeep Siddhartha                    throw new IllegalArgumentException("Model must not be null");
494f8cf71d753b86895f987f682c80491aa2967e0c2Sandeep Siddhartha                }
495f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            }
496f8cf71d753b86895f987f682c80491aa2967e0c2Sandeep Siddhartha
497f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
498f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha            try {
499452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                if (mDbHelper.updateKeyphraseSoundModel(model)) {
500452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    synchronized (this) {
501452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        // Notify the voice interaction service of a change in sound models.
502452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        if (mImpl != null && mImpl.mService != null) {
503452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                            mImpl.notifySoundModelsChangedLocked();
504452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        }
505452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    }
506452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    return SoundTriggerHelper.STATUS_OK;
507f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha                } else {
508452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    return SoundTriggerHelper.STATUS_ERROR;
509f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha                }
510452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            } finally {
511452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
512452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
513452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha        }
514452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha
515452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha        @Override
5168cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha        public int deleteKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
517452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            synchronized (this) {
518452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                if (mContext.checkCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
519452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        != PackageManager.PERMISSION_GRANTED) {
520452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    throw new SecurityException("Caller does not hold the permission "
521452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                            + Manifest.permission.MANAGE_VOICE_KEYPHRASES);
522452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                }
523452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
524452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha
5258cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            if (bcp47Locale == null) {
5268cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                throw new IllegalArgumentException(
5278cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                        "Illegal argument(s) in deleteKeyphraseSoundModel");
5288cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            }
5298cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha
5308cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            final int callingUid = UserHandle.getCallingUserId();
531452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
532256e1a62673472d685232d88ad4d067eb82deeacSandeep Siddhartha            boolean deleted = false;
533452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            try {
5348cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
535256e1a62673472d685232d88ad4d067eb82deeacSandeep Siddhartha                return deleted ? SoundTriggerHelper.STATUS_OK : SoundTriggerHelper.STATUS_ERROR;
536256e1a62673472d685232d88ad4d067eb82deeacSandeep Siddhartha            } finally {
537256e1a62673472d685232d88ad4d067eb82deeacSandeep Siddhartha                if (deleted) {
538f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha                    synchronized (this) {
5396daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha                        // Notify the voice interaction service of a change in sound models.
5406daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha                        if (mImpl != null && mImpl.mService != null) {
5416daae9622672e0b38fc2efed29f68061d749caccSandeep Siddhartha                            mImpl.notifySoundModelsChangedLocked();
542f8cf71d753b86895f987f682c80491aa2967e0c2Sandeep Siddhartha                        }
5432883ba69751de69811a38f086ecbe4c2032ca87dSandeep Siddhartha                    }
544d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep                }
545f63bc523eadbe01ce0a5ad52868a5dccb3d5f6ddSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
546d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep            }
547d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep        }
548d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep
549055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        //----------------- SoundTrigger APIs --------------------------------//
550055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        @Override
5518cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha        public boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
5528cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                String bcp47Locale) {
553452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            synchronized (this) {
554452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                if (mImpl == null || mImpl.mService == null
555452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        || service.asBinder() != mImpl.mService.asBinder()) {
556452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    throw new SecurityException(
557452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                            "Caller is not the current voice interaction service");
558452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                }
559452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
560452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha
5618cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            if (bcp47Locale == null) {
5628cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
5638cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            }
5648cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha
5658cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            final int callingUid = UserHandle.getCallingUserId();
566452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
567452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            try {
5688cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                KeyphraseSoundModel model =
5698cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                        mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
570452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                return model != null;
571452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            } finally {
572452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
573452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
574452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha        }
575452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha
576452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha        @Override
577055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
578055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            // Allow the call if this is the current voice interaction service.
579055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            synchronized (this) {
580055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                if (mImpl == null || mImpl.mService == null
581055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
582055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    throw new SecurityException(
583055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                            "Caller is not the current voice interaction service");
584055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                }
585055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
586055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                final long caller = Binder.clearCallingIdentity();
587055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                try {
588055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    return mSoundTriggerHelper.moduleProperties;
589055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                } finally {
590055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    Binder.restoreCallingIdentity(caller);
591055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                }
592055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            }
593055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        }
594055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
595055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        @Override
596055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        public int startRecognition(IVoiceInteractionService service, int keyphraseId,
5978cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                String bcp47Locale, IRecognitionStatusCallback callback,
5988cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                RecognitionConfig recognitionConfig) {
599055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            // Allow the call if this is the current voice interaction service.
600055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            synchronized (this) {
601055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                if (mImpl == null || mImpl.mService == null
602055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
603055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    throw new SecurityException(
604055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                            "Caller is not the current voice interaction service");
605055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                }
606055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
6078cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                if (callback == null || recognitionConfig == null || bcp47Locale == null) {
608452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
609452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                }
610452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
611452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha
6128cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha            int callingUid = UserHandle.getCallingUserId();
613452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
614452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            try {
6158cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                KeyphraseSoundModel soundModel =
6168cf8f71644643601fe8c3e9538fd00412b1ae8b1Sandeep Siddhartha                        mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
617452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                if (soundModel == null
618452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        || soundModel.uuid == null
619452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                        || soundModel.keyphrases == null) {
620452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    Slog.w(TAG, "No matching sound model found in startRecognition");
621452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                    return SoundTriggerHelper.STATUS_ERROR;
622452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                } else {
623055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    return mSoundTriggerHelper.startRecognition(
624055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                            keyphraseId, soundModel, callback, recognitionConfig);
625055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                }
626452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            } finally {
627452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
628055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            }
629055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        }
630055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
631055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        @Override
632055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
633055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                IRecognitionStatusCallback callback) {
634055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            // Allow the call if this is the current voice interaction service.
635055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            synchronized (this) {
636055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                if (mImpl == null || mImpl.mService == null
637055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                        || service == null || service.asBinder() != mImpl.mService.asBinder()) {
638055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                    throw new SecurityException(
639055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                            "Caller is not the current voice interaction service");
640055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha                }
641452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            }
642055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
643452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            final long caller = Binder.clearCallingIdentity();
644452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            try {
645452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                return mSoundTriggerHelper.stopRecognition(keyphraseId, callback);
646452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha            } finally {
647452a642430e3f8abfa053e48893dd0edfb12799bSandeep Siddhartha                Binder.restoreCallingIdentity(caller);
648055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha            }
649055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha        }
650055897208d659e9734a82def88be4a806ff55448Sandeep Siddhartha
651d7018200312e4e4dc3f67cf33dc90bf7ce585844Sandeep        @Override
65291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
65318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
65418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    != PackageManager.PERMISSION_GRANTED) {
65518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                pw.println("Permission Denial: can't dump PowerManager from from pid="
65618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        + Binder.getCallingPid()
65718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        + ", uid=" + Binder.getCallingUid());
65818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                return;
65918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            }
66018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            synchronized (this) {
66118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)\n");
66218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                if (mImpl == null) {
66318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    pw.println("  (No active implementation)");
66418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    return;
66518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                }
66618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                mImpl.dumpLocked(fd, pw, args);
66718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            }
6686b8556d2e320b631d3741bf064796efddb6e51dfSandeep Siddhartha            mSoundTriggerHelper.dump(fd, pw, args);
66991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
67091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
67191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        class SettingsObserver extends ContentObserver {
67291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            SettingsObserver(Handler handler) {
67391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                super(handler);
67491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                ContentResolver resolver = mContext.getContentResolver();
67591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                resolver.registerContentObserver(Settings.Secure.getUriFor(
67691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
67791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
67891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
67991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            @Override public void onChange(boolean selfChange) {
68091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                synchronized (VoiceInteractionManagerServiceStub.this) {
681c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                    switchImplementationIfNeededLocked(false);
68291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
68391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
68491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
68591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
68691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        PackageMonitor mPackageMonitor = new PackageMonitor() {
68791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            @Override
68891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
68991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                return super.onHandleForceStop(intent, packages, uid, doit);
69091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
69191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
69291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            @Override
69391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            public void onHandleUserStop(Intent intent, int userHandle) {
69491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
69591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
69691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            @Override
697a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn            public void onSomePackagesChanged() {
698a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                int userHandle = getChangingUserId();
699a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (DEBUG) Slog.i(TAG, "onSomePackagesChanged user=" + userHandle);
700a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
701a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                ComponentName curInteractor = getCurInteractor(userHandle);
702a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                ComponentName curRecognizer = getCurRecognizer(userHandle);
703a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (curRecognizer == null) {
704a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    // Could a new recognizer appear when we don't have one pre-installed?
705a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    if (anyPackagesAppearing()) {
706a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        curRecognizer = findAvailRecognizer(null, userHandle);
707a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        if (curRecognizer != null) {
708a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            setCurRecognizer(curRecognizer, userHandle);
709a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        }
710a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
711a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    return;
712a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
71391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
714a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (curInteractor != null) {
715a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    int change = isPackageDisappearing(curInteractor.getPackageName());
716a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    if (change == PACKAGE_PERMANENT_CHANGE) {
717a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        // The currently set interactor is permanently gone; fall back to
718a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        // the default config.
719a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        setCurInteractor(null, userHandle);
720a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        setCurRecognizer(null, userHandle);
721a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        initForUser(userHandle);
722a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        return;
723a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
724a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn
725a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    change = isPackageAppearing(curInteractor.getPackageName());
726a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    if (change != PACKAGE_UNCHANGED) {
727a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        // If current interactor is now appearing, for any reason, then
728a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        // restart our connection with it.
729a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        if (mImpl != null && curInteractor.getPackageName().equals(
730a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                                mImpl.mComponent.getPackageName())) {
731a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            switchImplementationIfNeededLocked(true);
732a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        }
733a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    }
734a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    return;
735c03c9167c2d9a1e22fb2b176b00a0524177fb037Dianne Hackborn                }
73691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
737a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                // There is no interactor, so just deal with a simple recognizer.
738a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                int change = isPackageDisappearing(curRecognizer.getPackageName());
739a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                if (change == PACKAGE_PERMANENT_CHANGE
740a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                        || change == PACKAGE_TEMPORARY_CHANGE) {
741a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);
74291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
743a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                } else if (isPackageModified(curRecognizer.getPackageName())) {
744a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                    setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(),
745a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                            userHandle), userHandle);
746a351ab96987381ffe7ea29a7cdec1e7fbd1497d5Dianne Hackborn                }
74791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
74891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        };
74991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
75091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn}
751