Home | History | Annotate | Download | only in server
      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