121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn/* 221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * Copyright (C) 2010 The Android Open Source Project 321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * 421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * you may not use this file except in compliance with the License. 621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * You may obtain a copy of the License at 721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * 821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * 1021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * Unless required by applicable law or agreed to in writing, software 1121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 1221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * See the License for the specific language governing permissions and 1421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn * limitations under the License. 1521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn */ 1621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 1721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornpackage com.android.server; 1821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 1921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor; 2021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 21f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.app.AppGlobals; 22f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.content.BroadcastReceiver; 2321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.ComponentName; 2421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.Context; 2521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.Intent; 26f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.content.IntentFilter; 27f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.content.pm.IPackageManager; 2821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.ResolveInfo; 2921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.ServiceInfo; 3021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.os.Binder; 31f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.os.RemoteException; 32f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasaniimport android.os.UserHandle; 3321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.provider.Settings; 3421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.speech.RecognitionService; 3521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.text.TextUtils; 368a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 3721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 3821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport java.util.List; 3921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 4021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornpublic class RecognitionManagerService extends Binder { 4121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn final static String TAG = "RecognitionManagerService"; 42f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 43f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani private final Context mContext; 44f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani private final MyPackageMonitor mMonitor; 45f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani private final IPackageManager mIPm; 46f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 47f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani private static final boolean DEBUG = false; 48f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 4921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn class MyPackageMonitor extends PackageMonitor { 5021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn public void onSomePackagesChanged() { 51f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani int userHandle = getChangingUserId(); 52f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (DEBUG) Slog.i(TAG, "onSomePackagesChanged user=" + userHandle); 53f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani ComponentName comp = getCurRecognizer(userHandle); 5421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (comp == null) { 5521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (anyPackagesAppearing()) { 56f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani comp = findAvailRecognizer(null, userHandle); 5721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (comp != null) { 58f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani setCurRecognizer(comp, userHandle); 5921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 6021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 6121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return; 6221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 63f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 6421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn int change = isPackageDisappearing(comp.getPackageName()); 6521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (change == PACKAGE_PERMANENT_CHANGE 6621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn || change == PACKAGE_TEMPORARY_CHANGE) { 67f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); 6821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn 6921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } else if (isPackageModified(comp.getPackageName())) { 70f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani setCurRecognizer(findAvailRecognizer(comp.getPackageName(), userHandle), 71f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani userHandle); 7221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 7321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 7421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 75f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 7621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn RecognitionManagerService(Context context) { 7721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn mContext = context; 7821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn mMonitor = new MyPackageMonitor(); 79f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani mMonitor.register(context, null, UserHandle.ALL, true); 80f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani mIPm = AppGlobals.getPackageManager(); 81f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 82f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); 8321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 84f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 8521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn public void systemReady() { 86f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani initForUser(UserHandle.USER_OWNER); 87f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani } 88f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 89f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani private void initForUser(int userHandle) { 90f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle); 91f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani ComponentName comp = getCurRecognizer(userHandle); 9221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (comp != null) { 9321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn // See if the current recognizer is no longer available. 9421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn try { 95f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani mIPm.getServiceInfo(comp, 0, userHandle); 96f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani } catch (RemoteException e) { 97f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani comp = findAvailRecognizer(null, userHandle); 98ddf322915ba87ef0bf604406ae441c63b371fda0Bjorn Bringert if (comp != null) { 99f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani setCurRecognizer(comp, userHandle); 100ddf322915ba87ef0bf604406ae441c63b371fda0Bjorn Bringert } 10121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 10221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } else { 103f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani comp = findAvailRecognizer(null, userHandle); 10421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (comp != null) { 105f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani setCurRecognizer(comp, userHandle); 10621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 10721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 10821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 109f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 110f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani ComponentName findAvailRecognizer(String prefPackage, int userHandle) { 11121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn List<ResolveInfo> available = 112f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani mContext.getPackageManager().queryIntentServicesAsUser( 113f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle); 11421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn int numAvailable = available.size(); 115f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 11621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (numAvailable == 0) { 117f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani Slog.w(TAG, "no available voice recognition services found for user " + userHandle); 11821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return null; 11921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } else { 12021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (prefPackage != null) { 12121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn for (int i=0; i<numAvailable; i++) { 12221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn ServiceInfo serviceInfo = available.get(i).serviceInfo; 12321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (prefPackage.equals(serviceInfo.packageName)) { 12421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return new ComponentName(serviceInfo.packageName, serviceInfo.name); 12521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 12621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 12721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 12821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (numAvailable > 1) { 1298a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "more than one voice recognition service found, picking first"); 13021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 131f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 13221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn ServiceInfo serviceInfo = available.get(0).serviceInfo; 13321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return new ComponentName(serviceInfo.packageName, serviceInfo.name); 13421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 13521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 136f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 137f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani ComponentName getCurRecognizer(int userHandle) { 138f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani String curRecognizer = Settings.Secure.getStringForUser( 13921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn mContext.getContentResolver(), 140f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle); 14121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn if (TextUtils.isEmpty(curRecognizer)) { 14221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return null; 14321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 144f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (DEBUG) Slog.i(TAG, "getCurRecognizer curRecognizer=" + curRecognizer 145f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani + " user=" + userHandle); 14621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn return ComponentName.unflattenFromString(curRecognizer); 14721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 148f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 149f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani void setCurRecognizer(ComponentName comp, int userHandle) { 150f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani Settings.Secure.putStringForUser(mContext.getContentResolver(), 15121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn Settings.Secure.VOICE_RECOGNITION_SERVICE, 152f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani comp != null ? comp.flattenToShortString() : "", userHandle); 153f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (DEBUG) Slog.i(TAG, "setCurRecognizer comp=" + comp 154f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani + " user=" + userHandle); 15521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn } 156f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani 157f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 158f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani public void onReceive(Context context, Intent intent) { 159f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani String action = intent.getAction(); 160f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (DEBUG) Slog.i(TAG, "received " + action); 161f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 162f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 163f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani if (userHandle > 0) { 164f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani initForUser(userHandle); 165f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani } 166f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani } 167f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani } 168f80a9b2f8a841d32c7398ebbf4cba82b02e9f167Amith Yamasani }; 16921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn} 170