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 17 package com.android.server; 18 19 import com.android.internal.content.PackageMonitor; 20 21 import android.app.AppGlobals; 22 import android.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.IPackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.ServiceInfo; 30 import android.os.Binder; 31 import android.os.RemoteException; 32 import android.os.UserHandle; 33 import android.provider.Settings; 34 import android.speech.RecognitionService; 35 import android.text.TextUtils; 36 import android.util.Slog; 37 38 import java.util.List; 39 40 public class RecognitionManagerService extends Binder { 41 final static String TAG = "RecognitionManagerService"; 42 43 private final Context mContext; 44 private final MyPackageMonitor mMonitor; 45 private final IPackageManager mIPm; 46 47 private static final boolean DEBUG = false; 48 49 class MyPackageMonitor extends PackageMonitor { 50 public void onSomePackagesChanged() { 51 int userHandle = getChangingUserId(); 52 if (DEBUG) Slog.i(TAG, "onSomePackagesChanged user=" + userHandle); 53 ComponentName comp = getCurRecognizer(userHandle); 54 if (comp == null) { 55 if (anyPackagesAppearing()) { 56 comp = findAvailRecognizer(null, userHandle); 57 if (comp != null) { 58 setCurRecognizer(comp, userHandle); 59 } 60 } 61 return; 62 } 63 64 int change = isPackageDisappearing(comp.getPackageName()); 65 if (change == PACKAGE_PERMANENT_CHANGE 66 || change == PACKAGE_TEMPORARY_CHANGE) { 67 setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle); 68 69 } else if (isPackageModified(comp.getPackageName())) { 70 setCurRecognizer(findAvailRecognizer(comp.getPackageName(), userHandle), 71 userHandle); 72 } 73 } 74 } 75 76 RecognitionManagerService(Context context) { 77 mContext = context; 78 mMonitor = new MyPackageMonitor(); 79 mMonitor.register(context, null, UserHandle.ALL, true); 80 mIPm = AppGlobals.getPackageManager(); 81 mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 82 new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); 83 } 84 85 public void systemReady() { 86 initForUser(UserHandle.USER_OWNER); 87 } 88 89 private void initForUser(int userHandle) { 90 if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle); 91 ComponentName comp = getCurRecognizer(userHandle); 92 ServiceInfo info = null; 93 if (comp != null) { 94 // See if the current recognizer is still available. 95 try { 96 info = mIPm.getServiceInfo(comp, 0, userHandle); 97 } catch (RemoteException e) { 98 } 99 } 100 if (info == null) { 101 comp = findAvailRecognizer(null, userHandle); 102 if (comp != null) { 103 setCurRecognizer(comp, userHandle); 104 } 105 } 106 } 107 108 ComponentName findAvailRecognizer(String prefPackage, int userHandle) { 109 List<ResolveInfo> available = 110 mContext.getPackageManager().queryIntentServicesAsUser( 111 new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle); 112 int numAvailable = available.size(); 113 114 if (numAvailable == 0) { 115 Slog.w(TAG, "no available voice recognition services found for user " + userHandle); 116 return null; 117 } else { 118 if (prefPackage != null) { 119 for (int i=0; i<numAvailable; i++) { 120 ServiceInfo serviceInfo = available.get(i).serviceInfo; 121 if (prefPackage.equals(serviceInfo.packageName)) { 122 return new ComponentName(serviceInfo.packageName, serviceInfo.name); 123 } 124 } 125 } 126 if (numAvailable > 1) { 127 Slog.w(TAG, "more than one voice recognition service found, picking first"); 128 } 129 130 ServiceInfo serviceInfo = available.get(0).serviceInfo; 131 return new ComponentName(serviceInfo.packageName, serviceInfo.name); 132 } 133 } 134 135 ComponentName getCurRecognizer(int userHandle) { 136 String curRecognizer = Settings.Secure.getStringForUser( 137 mContext.getContentResolver(), 138 Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle); 139 if (TextUtils.isEmpty(curRecognizer)) { 140 return null; 141 } 142 if (DEBUG) Slog.i(TAG, "getCurRecognizer curRecognizer=" + curRecognizer 143 + " user=" + userHandle); 144 return ComponentName.unflattenFromString(curRecognizer); 145 } 146 147 void setCurRecognizer(ComponentName comp, int userHandle) { 148 Settings.Secure.putStringForUser(mContext.getContentResolver(), 149 Settings.Secure.VOICE_RECOGNITION_SERVICE, 150 comp != null ? comp.flattenToShortString() : "", userHandle); 151 if (DEBUG) Slog.i(TAG, "setCurRecognizer comp=" + comp 152 + " user=" + userHandle); 153 } 154 155 BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 156 public void onReceive(Context context, Intent intent) { 157 String action = intent.getAction(); 158 if (DEBUG) Slog.i(TAG, "received " + action); 159 if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { 160 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 161 if (userHandle > 0) { 162 initForUser(userHandle); 163 } 164 } 165 } 166 }; 167 } 168