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
2121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.ComponentName;
2221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.Context;
2321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.Intent;
2421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.ResolveInfo;
2521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.ServiceInfo;
2621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
2721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.os.Binder;
2821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.provider.Settings;
2921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.speech.RecognitionService;
3021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.text.TextUtils;
318a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
3221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
3321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport java.util.List;
3421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
3521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornpublic class RecognitionManagerService extends Binder {
3621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    final static String TAG = "RecognitionManagerService";
3721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
3821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    final Context mContext;
3921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    final MyPackageMonitor mMonitor;
4021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
4121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
4321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            ComponentName comp = getCurRecognizer();
4421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (comp == null) {
4521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (anyPackagesAppearing()) {
4621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    comp = findAvailRecognizer(null);
4721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (comp != null) {
4821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        setCurRecognizer(comp);
4921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
5021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
5121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return;
5221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
5321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            int change = isPackageDisappearing(comp.getPackageName());
5521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (change == PACKAGE_PERMANENT_CHANGE
5621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    || change == PACKAGE_TEMPORARY_CHANGE) {
5721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                setCurRecognizer(findAvailRecognizer(null));
5821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } else if (isPackageModified(comp.getPackageName())) {
6021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                setCurRecognizer(findAvailRecognizer(comp.getPackageName()));
6121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
6221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
6321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
6421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
6521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    RecognitionManagerService(Context context) {
6621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        mContext = context;
6721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        mMonitor = new MyPackageMonitor();
6821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        mMonitor.register(context, true);
6921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
7021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
7121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    public void systemReady() {
7221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        ComponentName comp = getCurRecognizer();
7321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (comp != null) {
7421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            // See if the current recognizer is no longer available.
7521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            try {
7621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                mContext.getPackageManager().getServiceInfo(comp, 0);
7721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } catch (NameNotFoundException e) {
7821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                setCurRecognizer(null);
7921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
8021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        } else {
8121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            comp = findAvailRecognizer(null);
8221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (comp != null) {
8321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                setCurRecognizer(comp);
8421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
8521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
8621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
8721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
8821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    ComponentName findAvailRecognizer(String prefPackage) {
8921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        List<ResolveInfo> available =
9021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                mContext.getPackageManager().queryIntentServices(
9121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        new Intent(RecognitionService.SERVICE_INTERFACE), 0);
9221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        int numAvailable = available.size();
9321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
9421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (numAvailable == 0) {
958a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "no available voice recognition services found");
9621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return null;
9721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        } else {
9821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (prefPackage != null) {
9921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                for (int i=0; i<numAvailable; i++) {
10021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    ServiceInfo serviceInfo = available.get(i).serviceInfo;
10121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (prefPackage.equals(serviceInfo.packageName)) {
10221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        return new ComponentName(serviceInfo.packageName, serviceInfo.name);
10321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
10421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
10521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
10621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (numAvailable > 1) {
1078a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "more than one voice recognition service found, picking first");
10821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
10921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
11021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            ServiceInfo serviceInfo = available.get(0).serviceInfo;
11121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return new ComponentName(serviceInfo.packageName, serviceInfo.name);
11221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
11321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
11421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
11521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    ComponentName getCurRecognizer() {
11621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        String curRecognizer = Settings.Secure.getString(
11721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                mContext.getContentResolver(),
11821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Settings.Secure.VOICE_RECOGNITION_SERVICE);
11921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (TextUtils.isEmpty(curRecognizer)) {
12021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return null;
12121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
12221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        return ComponentName.unflattenFromString(curRecognizer);
12321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
12421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
12521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    void setCurRecognizer(ComponentName comp) {
12621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        Settings.Secure.putString(mContext.getContentResolver(),
12721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Settings.Secure.VOICE_RECOGNITION_SERVICE,
12821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                comp != null ? comp.flattenToShortString() : "");
12921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
13021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn}
131