1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import com.android.internal.content.PackageMonitor; 20 21import android.content.ComponentName; 22import android.content.Context; 23import android.content.Intent; 24import android.content.pm.ResolveInfo; 25import android.content.pm.ServiceInfo; 26import android.content.pm.PackageManager.NameNotFoundException; 27import android.os.Binder; 28import android.provider.Settings; 29import android.speech.RecognitionService; 30import android.text.TextUtils; 31import android.util.Slog; 32 33import java.util.List; 34 35public class RecognitionManagerService extends Binder { 36 final static String TAG = "RecognitionManagerService"; 37 38 final Context mContext; 39 final MyPackageMonitor mMonitor; 40 41 class MyPackageMonitor extends PackageMonitor { 42 public void onSomePackagesChanged() { 43 ComponentName comp = getCurRecognizer(); 44 if (comp == null) { 45 if (anyPackagesAppearing()) { 46 comp = findAvailRecognizer(null); 47 if (comp != null) { 48 setCurRecognizer(comp); 49 } 50 } 51 return; 52 } 53 54 int change = isPackageDisappearing(comp.getPackageName()); 55 if (change == PACKAGE_PERMANENT_CHANGE 56 || change == PACKAGE_TEMPORARY_CHANGE) { 57 setCurRecognizer(findAvailRecognizer(null)); 58 59 } else if (isPackageModified(comp.getPackageName())) { 60 setCurRecognizer(findAvailRecognizer(comp.getPackageName())); 61 } 62 } 63 } 64 65 RecognitionManagerService(Context context) { 66 mContext = context; 67 mMonitor = new MyPackageMonitor(); 68 mMonitor.register(context, true); 69 } 70 71 public void systemReady() { 72 ComponentName comp = getCurRecognizer(); 73 if (comp != null) { 74 // See if the current recognizer is no longer available. 75 try { 76 mContext.getPackageManager().getServiceInfo(comp, 0); 77 } catch (NameNotFoundException e) { 78 setCurRecognizer(null); 79 } 80 } else { 81 comp = findAvailRecognizer(null); 82 if (comp != null) { 83 setCurRecognizer(comp); 84 } 85 } 86 } 87 88 ComponentName findAvailRecognizer(String prefPackage) { 89 List<ResolveInfo> available = 90 mContext.getPackageManager().queryIntentServices( 91 new Intent(RecognitionService.SERVICE_INTERFACE), 0); 92 int numAvailable = available.size(); 93 94 if (numAvailable == 0) { 95 Slog.w(TAG, "no available voice recognition services found"); 96 return null; 97 } else { 98 if (prefPackage != null) { 99 for (int i=0; i<numAvailable; i++) { 100 ServiceInfo serviceInfo = available.get(i).serviceInfo; 101 if (prefPackage.equals(serviceInfo.packageName)) { 102 return new ComponentName(serviceInfo.packageName, serviceInfo.name); 103 } 104 } 105 } 106 if (numAvailable > 1) { 107 Slog.w(TAG, "more than one voice recognition service found, picking first"); 108 } 109 110 ServiceInfo serviceInfo = available.get(0).serviceInfo; 111 return new ComponentName(serviceInfo.packageName, serviceInfo.name); 112 } 113 } 114 115 ComponentName getCurRecognizer() { 116 String curRecognizer = Settings.Secure.getString( 117 mContext.getContentResolver(), 118 Settings.Secure.VOICE_RECOGNITION_SERVICE); 119 if (TextUtils.isEmpty(curRecognizer)) { 120 return null; 121 } 122 return ComponentName.unflattenFromString(curRecognizer); 123 } 124 125 void setCurRecognizer(ComponentName comp) { 126 Settings.Secure.putString(mContext.getContentResolver(), 127 Settings.Secure.VOICE_RECOGNITION_SERVICE, 128 comp != null ? comp.flattenToShortString() : ""); 129 } 130} 131