Home | History | Annotate | Download | only in voiceinteraction
      1 /*
      2  * Copyright (C) 2014 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.voiceinteraction;
     18 
     19 import android.Manifest;
     20 import android.app.ActivityManager;
     21 import android.app.ActivityManagerInternal;
     22 import android.app.AppGlobals;
     23 import android.content.ComponentName;
     24 import android.content.ContentResolver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.pm.ApplicationInfo;
     28 import android.content.pm.IPackageManager;
     29 import android.content.pm.PackageManager;
     30 import android.content.pm.PackageManagerInternal;
     31 import android.content.pm.ResolveInfo;
     32 import android.content.pm.ServiceInfo;
     33 import android.content.res.Resources;
     34 import android.database.ContentObserver;
     35 import android.hardware.soundtrigger.IRecognitionStatusCallback;
     36 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
     37 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
     38 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
     39 import android.os.Binder;
     40 import android.os.Bundle;
     41 import android.os.Handler;
     42 import android.os.IBinder;
     43 import android.os.Parcel;
     44 import android.os.RemoteCallbackList;
     45 import android.os.RemoteException;
     46 import android.os.UserHandle;
     47 import android.provider.Settings;
     48 import android.service.voice.IVoiceInteractionService;
     49 import android.service.voice.IVoiceInteractionSession;
     50 import android.service.voice.VoiceInteractionManagerInternal;
     51 import android.service.voice.VoiceInteractionService;
     52 import android.service.voice.VoiceInteractionServiceInfo;
     53 import android.service.voice.VoiceInteractionSession;
     54 import android.speech.RecognitionService;
     55 import android.text.TextUtils;
     56 import android.util.Log;
     57 import android.util.Slog;
     58 
     59 import com.android.internal.app.IVoiceInteractionSessionListener;
     60 import com.android.internal.app.IVoiceInteractionManagerService;
     61 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
     62 import com.android.internal.app.IVoiceInteractor;
     63 import com.android.internal.content.PackageMonitor;
     64 import com.android.internal.os.BackgroundThread;
     65 import com.android.server.LocalServices;
     66 import com.android.server.SystemService;
     67 import com.android.server.UiThread;
     68 import com.android.server.soundtrigger.SoundTriggerInternal;
     69 
     70 import java.io.FileDescriptor;
     71 import java.io.PrintWriter;
     72 import java.util.List;
     73 import java.util.TreeSet;
     74 
     75 /**
     76  * SystemService that publishes an IVoiceInteractionManagerService.
     77  */
     78 public class VoiceInteractionManagerService extends SystemService {
     79     static final String TAG = "VoiceInteractionManagerService";
     80     static final boolean DEBUG = false;
     81 
     82     final Context mContext;
     83     final ContentResolver mResolver;
     84     final DatabaseHelper mDbHelper;
     85     final ActivityManagerInternal mAmInternal;
     86     final TreeSet<Integer> mLoadedKeyphraseIds;
     87     SoundTriggerInternal mSoundTriggerInternal;
     88 
     89     private final RemoteCallbackList<IVoiceInteractionSessionListener>
     90             mVoiceInteractionSessionListeners = new RemoteCallbackList<>();
     91 
     92     public VoiceInteractionManagerService(Context context) {
     93         super(context);
     94         mContext = context;
     95         mResolver = context.getContentResolver();
     96         mDbHelper = new DatabaseHelper(context);
     97         mServiceStub = new VoiceInteractionManagerServiceStub();
     98         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
     99         mLoadedKeyphraseIds = new TreeSet<Integer>();
    100 
    101         PackageManagerInternal packageManagerInternal = LocalServices.getService(
    102                 PackageManagerInternal.class);
    103         packageManagerInternal.setVoiceInteractionPackagesProvider(
    104                 new PackageManagerInternal.PackagesProvider() {
    105             @Override
    106             public String[] getPackages(int userId) {
    107                 mServiceStub.initForUser(userId);
    108                 ComponentName interactor = mServiceStub.getCurInteractor(userId);
    109                 if (interactor != null) {
    110                     return new String[] {interactor.getPackageName()};
    111                 }
    112                 return null;
    113             }
    114         });
    115     }
    116 
    117     @Override
    118     public void onStart() {
    119         publishBinderService(Context.VOICE_INTERACTION_MANAGER_SERVICE, mServiceStub);
    120         publishLocalService(VoiceInteractionManagerInternal.class, new LocalService());
    121     }
    122 
    123     @Override
    124     public void onBootPhase(int phase) {
    125         if (PHASE_SYSTEM_SERVICES_READY == phase) {
    126             mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
    127         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
    128             mServiceStub.systemRunning(isSafeMode());
    129         }
    130     }
    131 
    132     @Override
    133     public void onStartUser(int userHandle) {
    134         mServiceStub.initForUser(userHandle);
    135     }
    136 
    137     @Override
    138     public void onUnlockUser(int userHandle) {
    139         mServiceStub.initForUser(userHandle);
    140         mServiceStub.switchImplementationIfNeeded(false);
    141     }
    142 
    143     @Override
    144     public void onSwitchUser(int userHandle) {
    145         mServiceStub.switchUser(userHandle);
    146     }
    147 
    148     class LocalService extends VoiceInteractionManagerInternal {
    149         @Override
    150         public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
    151             if (DEBUG) {
    152                 Slog.i(TAG, "startLocalVoiceInteraction " + callingActivity);
    153             }
    154             VoiceInteractionManagerService.this.mServiceStub.startLocalVoiceInteraction(
    155                     callingActivity, options);
    156         }
    157 
    158         @Override
    159         public boolean supportsLocalVoiceInteraction() {
    160             return VoiceInteractionManagerService.this.mServiceStub.supportsLocalVoiceInteraction();
    161         }
    162 
    163         @Override
    164         public void stopLocalVoiceInteraction(IBinder callingActivity) {
    165             if (DEBUG) {
    166                 Slog.i(TAG, "stopLocalVoiceInteraction " + callingActivity);
    167             }
    168             VoiceInteractionManagerService.this.mServiceStub.stopLocalVoiceInteraction(
    169                     callingActivity);
    170         }
    171     }
    172 
    173     // implementation entry point and binder service
    174     private final VoiceInteractionManagerServiceStub mServiceStub;
    175 
    176     class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
    177 
    178         VoiceInteractionManagerServiceImpl mImpl;
    179 
    180         private boolean mSafeMode;
    181         private int mCurUser;
    182         private final boolean mEnableService;
    183 
    184         VoiceInteractionManagerServiceStub() {
    185             mEnableService = shouldEnableService(mContext.getResources());
    186         }
    187 
    188         // TODO: VI Make sure the caller is the current user or profile
    189         void startLocalVoiceInteraction(final IBinder token, Bundle options) {
    190             if (mImpl == null) return;
    191 
    192             final long caller = Binder.clearCallingIdentity();
    193             try {
    194                 mImpl.showSessionLocked(options,
    195                         VoiceInteractionSession.SHOW_SOURCE_ACTIVITY,
    196                         new IVoiceInteractionSessionShowCallback.Stub() {
    197                             @Override
    198                             public void onFailed() {
    199                             }
    200 
    201                             @Override
    202                             public void onShown() {
    203                                 mAmInternal.onLocalVoiceInteractionStarted(token,
    204                                         mImpl.mActiveSession.mSession,
    205                                         mImpl.mActiveSession.mInteractor);
    206                             }
    207                         },
    208                         token);
    209             } finally {
    210                 Binder.restoreCallingIdentity(caller);
    211             }
    212         }
    213 
    214         public void stopLocalVoiceInteraction(IBinder callingActivity) {
    215             if (mImpl == null) return;
    216 
    217             final long caller = Binder.clearCallingIdentity();
    218             try {
    219                 mImpl.finishLocked(callingActivity, true);
    220             } finally {
    221                 Binder.restoreCallingIdentity(caller);
    222             }
    223         }
    224 
    225         public boolean supportsLocalVoiceInteraction() {
    226             if (mImpl == null) return false;
    227 
    228             return mImpl.supportsLocalVoiceInteraction();
    229         }
    230 
    231         @Override
    232         public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    233                 throws RemoteException {
    234             try {
    235                 return super.onTransact(code, data, reply, flags);
    236             } catch (RuntimeException e) {
    237                 // The activity manager only throws security exceptions, so let's
    238                 // log all others.
    239                 if (!(e instanceof SecurityException)) {
    240                     Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
    241                 }
    242                 throw e;
    243             }
    244         }
    245 
    246         public void initForUser(int userHandle) {
    247             if (DEBUG) Slog.d(TAG, "**************** initForUser user=" + userHandle);
    248             String curInteractorStr = Settings.Secure.getStringForUser(
    249                     mContext.getContentResolver(),
    250                     Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
    251             ComponentName curRecognizer = getCurRecognizer(userHandle);
    252             VoiceInteractionServiceInfo curInteractorInfo = null;
    253             if (DEBUG) Slog.d(TAG, "curInteractorStr=" + curInteractorStr
    254                     + " curRecognizer=" + curRecognizer);
    255             if (curInteractorStr == null && curRecognizer != null && mEnableService) {
    256                 // If there is no interactor setting, that means we are upgrading
    257                 // from an older platform version.  If the current recognizer is not
    258                 // set or matches the preferred recognizer, then we want to upgrade
    259                 // the user to have the default voice interaction service enabled.
    260                 // Note that we don't do this for low-RAM devices, since we aren't
    261                 // supporting voice interaction services there.
    262                 curInteractorInfo = findAvailInteractor(userHandle, curRecognizer.getPackageName());
    263                 if (curInteractorInfo != null) {
    264                     // Looks good!  We'll apply this one.  To make it happen, we clear the
    265                     // recognizer so that we don't think we have anything set and will
    266                     // re-apply the settings.
    267                     if (DEBUG) Slog.d(TAG, "No set interactor, found avail: "
    268                             + curInteractorInfo.getServiceInfo().name);
    269                     curRecognizer = null;
    270                 }
    271             }
    272 
    273             // If forceInteractorPackage exists, try to apply the interactor from this package if
    274             // possible and ignore the regular interactor setting.
    275             String forceInteractorPackage =
    276                     getForceVoiceInteractionServicePackage(mContext.getResources());
    277             if (forceInteractorPackage != null) {
    278                 curInteractorInfo = findAvailInteractor(userHandle, forceInteractorPackage);
    279                 if (curInteractorInfo != null) {
    280                     // We'll apply this one. Clear the recognizer and re-apply the settings.
    281                     curRecognizer = null;
    282                 }
    283             }
    284 
    285             // If we are on a svelte device, make sure an interactor is not currently
    286             // enabled; if it is, turn it off.
    287             if (!mEnableService && curInteractorStr != null) {
    288                 if (!TextUtils.isEmpty(curInteractorStr)) {
    289                     if (DEBUG) Slog.d(TAG, "Svelte device; disabling interactor");
    290                     setCurInteractor(null, userHandle);
    291                     curInteractorStr = "";
    292                 }
    293             }
    294 
    295             if (curRecognizer != null) {
    296                 // If we already have at least a recognizer, then we probably want to
    297                 // leave things as they are...  unless something has disappeared.
    298                 IPackageManager pm = AppGlobals.getPackageManager();
    299                 ServiceInfo interactorInfo = null;
    300                 ServiceInfo recognizerInfo = null;
    301                 ComponentName curInteractor = !TextUtils.isEmpty(curInteractorStr)
    302                         ? ComponentName.unflattenFromString(curInteractorStr) : null;
    303                 try {
    304                     recognizerInfo = pm.getServiceInfo(curRecognizer, 0, userHandle);
    305                     if (curInteractor != null) {
    306                         interactorInfo = pm.getServiceInfo(curInteractor, 0, userHandle);
    307                     }
    308                 } catch (RemoteException e) {
    309                 }
    310                 // If the apps for the currently set components still exist, then all is okay.
    311                 if (recognizerInfo != null && (curInteractor == null || interactorInfo != null)) {
    312                     if (DEBUG) Slog.d(TAG, "Current interactor/recognizer okay, done!");
    313                     return;
    314                 }
    315                 if (DEBUG) Slog.d(TAG, "Bad recognizer (" + recognizerInfo + ") or interactor ("
    316                         + interactorInfo + ")");
    317             }
    318 
    319             // Initializing settings, look for an interactor first (but only on non-svelte).
    320             if (curInteractorInfo == null && mEnableService) {
    321                 curInteractorInfo = findAvailInteractor(userHandle, null);
    322             }
    323 
    324             if (curInteractorInfo != null) {
    325                 // Eventually it will be an error to not specify this.
    326                 setCurInteractor(new ComponentName(curInteractorInfo.getServiceInfo().packageName,
    327                         curInteractorInfo.getServiceInfo().name), userHandle);
    328                 if (curInteractorInfo.getRecognitionService() != null) {
    329                     setCurRecognizer(
    330                             new ComponentName(curInteractorInfo.getServiceInfo().packageName,
    331                                     curInteractorInfo.getRecognitionService()), userHandle);
    332                     return;
    333                 }
    334             }
    335 
    336             // No voice interactor, we'll just set up a simple recognizer.
    337             curRecognizer = findAvailRecognizer(null, userHandle);
    338             if (curRecognizer != null) {
    339                 if (curInteractorInfo == null) {
    340                     setCurInteractor(null, userHandle);
    341                 }
    342                 setCurRecognizer(curRecognizer, userHandle);
    343             }
    344         }
    345 
    346         private boolean shouldEnableService(Resources res) {
    347             // VoiceInteractionService should not be enabled on low ram devices unless it has the config flag.
    348             return !ActivityManager.isLowRamDeviceStatic() ||
    349                     getForceVoiceInteractionServicePackage(res) != null;
    350         }
    351 
    352         private String getForceVoiceInteractionServicePackage(Resources res) {
    353             String interactorPackage =
    354                     res.getString(com.android.internal.R.string.config_forceVoiceInteractionServicePackage);
    355             return TextUtils.isEmpty(interactorPackage) ? null : interactorPackage;
    356         }
    357 
    358         public void systemRunning(boolean safeMode) {
    359             mSafeMode = safeMode;
    360 
    361             mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(),
    362                     UserHandle.ALL, true);
    363             new SettingsObserver(UiThread.getHandler());
    364 
    365             synchronized (this) {
    366                 mCurUser = ActivityManager.getCurrentUser();
    367                 switchImplementationIfNeededLocked(false);
    368             }
    369         }
    370 
    371         public void switchUser(int userHandle) {
    372             synchronized (this) {
    373                 mCurUser = userHandle;
    374                 switchImplementationIfNeededLocked(false);
    375             }
    376         }
    377 
    378         void switchImplementationIfNeeded(boolean force) {
    379             synchronized (this) {
    380                 switchImplementationIfNeededLocked(force);
    381             }
    382         }
    383 
    384         void switchImplementationIfNeededLocked(boolean force) {
    385             if (!mSafeMode) {
    386                 String curService = Settings.Secure.getStringForUser(
    387                         mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
    388                 ComponentName serviceComponent = null;
    389                 ServiceInfo serviceInfo = null;
    390                 if (curService != null && !curService.isEmpty()) {
    391                     try {
    392                         serviceComponent = ComponentName.unflattenFromString(curService);
    393                         serviceInfo = AppGlobals.getPackageManager()
    394                                 .getServiceInfo(serviceComponent, 0, mCurUser);
    395                     } catch (RuntimeException | RemoteException e) {
    396                         Slog.wtf(TAG, "Bad voice interaction service name " + curService, e);
    397                         serviceComponent = null;
    398                         serviceInfo = null;
    399                     }
    400                 }
    401 
    402                 if (force || mImpl == null || mImpl.mUser != mCurUser
    403                         || !mImpl.mComponent.equals(serviceComponent)) {
    404                     unloadAllKeyphraseModels();
    405                     if (mImpl != null) {
    406                         mImpl.shutdownLocked();
    407                     }
    408                     if (serviceComponent != null && serviceInfo != null) {
    409                         mImpl = new VoiceInteractionManagerServiceImpl(mContext,
    410                                 UiThread.getHandler(), this, mCurUser, serviceComponent);
    411                         mImpl.startLocked();
    412                     } else {
    413                         mImpl = null;
    414                     }
    415                 }
    416             }
    417         }
    418 
    419         VoiceInteractionServiceInfo findAvailInteractor(int userHandle, String packageName) {
    420             List<ResolveInfo> available =
    421                     mContext.getPackageManager().queryIntentServicesAsUser(
    422                             new Intent(VoiceInteractionService.SERVICE_INTERFACE),
    423                             PackageManager.MATCH_DIRECT_BOOT_AWARE
    424                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
    425                                     | PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userHandle);
    426             int numAvailable = available.size();
    427 
    428             if (numAvailable == 0) {
    429                 Slog.w(TAG, "no available voice interaction services found for user " + userHandle);
    430                 return null;
    431             } else {
    432                 // Find first system package.  We never want to allow third party services to
    433                 // be automatically selected, because those require approval of the user.
    434                 VoiceInteractionServiceInfo foundInfo = null;
    435                 for (int i=0; i<numAvailable; i++) {
    436                     ServiceInfo cur = available.get(i).serviceInfo;
    437                     if ((cur.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
    438                         ComponentName comp = new ComponentName(cur.packageName, cur.name);
    439                         try {
    440                             VoiceInteractionServiceInfo info = new VoiceInteractionServiceInfo(
    441                                     mContext.getPackageManager(), comp, userHandle);
    442                             if (info.getParseError() == null) {
    443                                 if (packageName == null || info.getServiceInfo().packageName.equals(
    444                                         packageName)) {
    445                                     if (foundInfo == null) {
    446                                         foundInfo = info;
    447                                     } else {
    448                                         Slog.w(TAG, "More than one voice interaction service, "
    449                                                 + "picking first "
    450                                                 + new ComponentName(
    451                                                         foundInfo.getServiceInfo().packageName,
    452                                                         foundInfo.getServiceInfo().name)
    453                                                 + " over "
    454                                                 + new ComponentName(cur.packageName, cur.name));
    455                                     }
    456                                 }
    457                             } else {
    458                                 Slog.w(TAG, "Bad interaction service " + comp + ": "
    459                                         + info.getParseError());
    460                             }
    461                         } catch (PackageManager.NameNotFoundException e) {
    462                             Slog.w(TAG, "Failure looking up interaction service " + comp);
    463                         }
    464                     }
    465                 }
    466 
    467                 return foundInfo;
    468             }
    469         }
    470 
    471         ComponentName getCurInteractor(int userHandle) {
    472             String curInteractor = Settings.Secure.getStringForUser(
    473                     mContext.getContentResolver(),
    474                     Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
    475             if (TextUtils.isEmpty(curInteractor)) {
    476                 return null;
    477             }
    478             if (DEBUG) Slog.d(TAG, "getCurInteractor curInteractor=" + curInteractor
    479                     + " user=" + userHandle);
    480             return ComponentName.unflattenFromString(curInteractor);
    481         }
    482 
    483         void setCurInteractor(ComponentName comp, int userHandle) {
    484             Settings.Secure.putStringForUser(mContext.getContentResolver(),
    485                     Settings.Secure.VOICE_INTERACTION_SERVICE,
    486                     comp != null ? comp.flattenToShortString() : "", userHandle);
    487             if (DEBUG) Slog.d(TAG, "setCurInteractor comp=" + comp
    488                     + " user=" + userHandle);
    489         }
    490 
    491         ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
    492             List<ResolveInfo> available =
    493                     mContext.getPackageManager().queryIntentServicesAsUser(
    494                             new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle);
    495             int numAvailable = available.size();
    496 
    497             if (numAvailable == 0) {
    498                 Slog.w(TAG, "no available voice recognition services found for user " + userHandle);
    499                 return null;
    500             } else {
    501                 if (prefPackage != null) {
    502                     for (int i=0; i<numAvailable; i++) {
    503                         ServiceInfo serviceInfo = available.get(i).serviceInfo;
    504                         if (prefPackage.equals(serviceInfo.packageName)) {
    505                             return new ComponentName(serviceInfo.packageName, serviceInfo.name);
    506                         }
    507                     }
    508                 }
    509                 if (numAvailable > 1) {
    510                     Slog.w(TAG, "more than one voice recognition service found, picking first");
    511                 }
    512 
    513                 ServiceInfo serviceInfo = available.get(0).serviceInfo;
    514                 return new ComponentName(serviceInfo.packageName, serviceInfo.name);
    515             }
    516         }
    517 
    518         ComponentName getCurRecognizer(int userHandle) {
    519             String curRecognizer = Settings.Secure.getStringForUser(
    520                     mContext.getContentResolver(),
    521                     Settings.Secure.VOICE_RECOGNITION_SERVICE, userHandle);
    522             if (TextUtils.isEmpty(curRecognizer)) {
    523                 return null;
    524             }
    525             if (DEBUG) Slog.d(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
    526                     + " user=" + userHandle);
    527             return ComponentName.unflattenFromString(curRecognizer);
    528         }
    529 
    530         void setCurRecognizer(ComponentName comp, int userHandle) {
    531             Settings.Secure.putStringForUser(mContext.getContentResolver(),
    532                     Settings.Secure.VOICE_RECOGNITION_SERVICE,
    533                     comp != null ? comp.flattenToShortString() : "", userHandle);
    534             if (DEBUG) Slog.d(TAG, "setCurRecognizer comp=" + comp
    535                     + " user=" + userHandle);
    536         }
    537 
    538         void resetCurAssistant(int userHandle) {
    539             Settings.Secure.putStringForUser(mContext.getContentResolver(),
    540                     Settings.Secure.ASSISTANT, null, userHandle);
    541         }
    542 
    543         @Override
    544         public void showSession(IVoiceInteractionService service, Bundle args, int flags) {
    545             synchronized (this) {
    546                 if (mImpl == null || mImpl.mService == null
    547                         || service.asBinder() != mImpl.mService.asBinder()) {
    548                     throw new SecurityException(
    549                             "Caller is not the current voice interaction service");
    550                 }
    551                 final long caller = Binder.clearCallingIdentity();
    552                 try {
    553                     mImpl.showSessionLocked(args, flags, null, null);
    554                 } finally {
    555                     Binder.restoreCallingIdentity(caller);
    556                 }
    557             }
    558         }
    559 
    560         @Override
    561         public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
    562                 IVoiceInteractor interactor) {
    563             synchronized (this) {
    564                 if (mImpl == null) {
    565                     throw new SecurityException(
    566                             "deliverNewSession without running voice interaction service");
    567                 }
    568                 final long caller = Binder.clearCallingIdentity();
    569                 try {
    570                     return mImpl.deliverNewSessionLocked(token, session, interactor);
    571                 } finally {
    572                     Binder.restoreCallingIdentity(caller);
    573                 }
    574             }
    575         }
    576 
    577         @Override
    578         public boolean showSessionFromSession(IBinder token, Bundle sessionArgs, int flags) {
    579             synchronized (this) {
    580                 if (mImpl == null) {
    581                     Slog.w(TAG, "showSessionFromSession without running voice interaction service");
    582                     return false;
    583                 }
    584                 final long caller = Binder.clearCallingIdentity();
    585                 try {
    586                     return mImpl.showSessionLocked(sessionArgs, flags, null, null);
    587                 } finally {
    588                     Binder.restoreCallingIdentity(caller);
    589                 }
    590             }
    591         }
    592 
    593         @Override
    594         public boolean hideSessionFromSession(IBinder token) {
    595             synchronized (this) {
    596                 if (mImpl == null) {
    597                     Slog.w(TAG, "hideSessionFromSession without running voice interaction service");
    598                     return false;
    599                 }
    600                 final long caller = Binder.clearCallingIdentity();
    601                 try {
    602                     return mImpl.hideSessionLocked();
    603                 } finally {
    604                     Binder.restoreCallingIdentity(caller);
    605                 }
    606             }
    607         }
    608 
    609         @Override
    610         public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
    611             synchronized (this) {
    612                 if (mImpl == null) {
    613                     Slog.w(TAG, "startVoiceActivity without running voice interaction service");
    614                     return ActivityManager.START_CANCELED;
    615                 }
    616                 final int callingPid = Binder.getCallingPid();
    617                 final int callingUid = Binder.getCallingUid();
    618                 final long caller = Binder.clearCallingIdentity();
    619                 try {
    620                     return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
    621                             intent, resolvedType);
    622                 } finally {
    623                     Binder.restoreCallingIdentity(caller);
    624                 }
    625             }
    626         }
    627 
    628         @Override
    629         public void setKeepAwake(IBinder token, boolean keepAwake) {
    630             synchronized (this) {
    631                 if (mImpl == null) {
    632                     Slog.w(TAG, "setKeepAwake without running voice interaction service");
    633                     return;
    634                 }
    635                 final long caller = Binder.clearCallingIdentity();
    636                 try {
    637                     mImpl.setKeepAwakeLocked(token, keepAwake);
    638                 } finally {
    639                     Binder.restoreCallingIdentity(caller);
    640                 }
    641             }
    642         }
    643 
    644         @Override
    645         public void closeSystemDialogs(IBinder token) {
    646             synchronized (this) {
    647                 if (mImpl == null) {
    648                     Slog.w(TAG, "closeSystemDialogs without running voice interaction service");
    649                     return;
    650                 }
    651                 final long caller = Binder.clearCallingIdentity();
    652                 try {
    653                     mImpl.closeSystemDialogsLocked(token);
    654                 } finally {
    655                     Binder.restoreCallingIdentity(caller);
    656                 }
    657             }
    658         }
    659 
    660         @Override
    661         public void finish(IBinder token) {
    662             synchronized (this) {
    663                 if (mImpl == null) {
    664                     Slog.w(TAG, "finish without running voice interaction service");
    665                     return;
    666                 }
    667                 final long caller = Binder.clearCallingIdentity();
    668                 try {
    669                     mImpl.finishLocked(token, false);
    670                 } finally {
    671                     Binder.restoreCallingIdentity(caller);
    672                 }
    673             }
    674         }
    675 
    676         @Override
    677         public void setDisabledShowContext(int flags) {
    678             synchronized (this) {
    679                 if (mImpl == null) {
    680                     Slog.w(TAG, "setDisabledShowContext without running voice interaction service");
    681                     return;
    682                 }
    683                 final int callingUid = Binder.getCallingUid();
    684                 final long caller = Binder.clearCallingIdentity();
    685                 try {
    686                     mImpl.setDisabledShowContextLocked(callingUid, flags);
    687                 } finally {
    688                     Binder.restoreCallingIdentity(caller);
    689                 }
    690             }
    691         }
    692 
    693         @Override
    694         public int getDisabledShowContext() {
    695             synchronized (this) {
    696                 if (mImpl == null) {
    697                     Slog.w(TAG, "getDisabledShowContext without running voice interaction service");
    698                     return 0;
    699                 }
    700                 final int callingUid = Binder.getCallingUid();
    701                 final long caller = Binder.clearCallingIdentity();
    702                 try {
    703                     return mImpl.getDisabledShowContextLocked(callingUid);
    704                 } finally {
    705                     Binder.restoreCallingIdentity(caller);
    706                 }
    707             }
    708         }
    709 
    710         @Override
    711         public int getUserDisabledShowContext() {
    712             synchronized (this) {
    713                 if (mImpl == null) {
    714                     Slog.w(TAG,
    715                             "getUserDisabledShowContext without running voice interaction service");
    716                     return 0;
    717                 }
    718                 final int callingUid = Binder.getCallingUid();
    719                 final long caller = Binder.clearCallingIdentity();
    720                 try {
    721                     return mImpl.getUserDisabledShowContextLocked(callingUid);
    722                 } finally {
    723                     Binder.restoreCallingIdentity(caller);
    724                 }
    725             }
    726         }
    727 
    728         //----------------- Model management APIs --------------------------------//
    729 
    730         @Override
    731         public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
    732             enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
    733 
    734             if (bcp47Locale == null) {
    735                 throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
    736             }
    737 
    738             final int callingUid = UserHandle.getCallingUserId();
    739             final long caller = Binder.clearCallingIdentity();
    740             try {
    741                 return mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
    742             } finally {
    743                 Binder.restoreCallingIdentity(caller);
    744             }
    745         }
    746 
    747         @Override
    748         public int updateKeyphraseSoundModel(KeyphraseSoundModel model) {
    749             enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
    750             if (model == null) {
    751                 throw new IllegalArgumentException("Model must not be null");
    752             }
    753 
    754             final long caller = Binder.clearCallingIdentity();
    755             try {
    756                 if (mDbHelper.updateKeyphraseSoundModel(model)) {
    757                     synchronized (this) {
    758                         // Notify the voice interaction service of a change in sound models.
    759                         if (mImpl != null && mImpl.mService != null) {
    760                             mImpl.notifySoundModelsChangedLocked();
    761                         }
    762                     }
    763                     return SoundTriggerInternal.STATUS_OK;
    764                 } else {
    765                     return SoundTriggerInternal.STATUS_ERROR;
    766                 }
    767             } finally {
    768                 Binder.restoreCallingIdentity(caller);
    769             }
    770         }
    771 
    772         @Override
    773         public int deleteKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
    774             enforceCallingPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES);
    775 
    776             if (bcp47Locale == null) {
    777                 throw new IllegalArgumentException(
    778                         "Illegal argument(s) in deleteKeyphraseSoundModel");
    779             }
    780 
    781             final int callingUid = UserHandle.getCallingUserId();
    782             final long caller = Binder.clearCallingIdentity();
    783             boolean deleted = false;
    784             try {
    785                 int unloadStatus = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
    786                 if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
    787                     Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
    788                 }
    789                 deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
    790                 return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
    791             } finally {
    792                 if (deleted) {
    793                     synchronized (this) {
    794                         // Notify the voice interaction service of a change in sound models.
    795                         if (mImpl != null && mImpl.mService != null) {
    796                             mImpl.notifySoundModelsChangedLocked();
    797                         }
    798                         mLoadedKeyphraseIds.remove(keyphraseId);
    799                     }
    800                 }
    801                 Binder.restoreCallingIdentity(caller);
    802             }
    803         }
    804 
    805         //----------------- SoundTrigger APIs --------------------------------//
    806         @Override
    807         public boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
    808                 String bcp47Locale) {
    809             synchronized (this) {
    810                 if (mImpl == null || mImpl.mService == null
    811                         || service.asBinder() != mImpl.mService.asBinder()) {
    812                     throw new SecurityException(
    813                             "Caller is not the current voice interaction service");
    814                 }
    815             }
    816 
    817             if (bcp47Locale == null) {
    818                 throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
    819             }
    820 
    821             final int callingUid = UserHandle.getCallingUserId();
    822             final long caller = Binder.clearCallingIdentity();
    823             try {
    824                 KeyphraseSoundModel model =
    825                         mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
    826                 return model != null;
    827             } finally {
    828                 Binder.restoreCallingIdentity(caller);
    829             }
    830         }
    831 
    832         @Override
    833         public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
    834             // Allow the call if this is the current voice interaction service.
    835             synchronized (this) {
    836                 if (mImpl == null || mImpl.mService == null
    837                         || service == null || service.asBinder() != mImpl.mService.asBinder()) {
    838                     throw new SecurityException(
    839                             "Caller is not the current voice interaction service");
    840                 }
    841 
    842                 final long caller = Binder.clearCallingIdentity();
    843                 try {
    844                     return mSoundTriggerInternal.getModuleProperties();
    845                 } finally {
    846                     Binder.restoreCallingIdentity(caller);
    847                 }
    848             }
    849         }
    850 
    851         @Override
    852         public int startRecognition(IVoiceInteractionService service, int keyphraseId,
    853                 String bcp47Locale, IRecognitionStatusCallback callback,
    854                 RecognitionConfig recognitionConfig) {
    855             // Allow the call if this is the current voice interaction service.
    856             synchronized (this) {
    857                 if (mImpl == null || mImpl.mService == null
    858                         || service == null || service.asBinder() != mImpl.mService.asBinder()) {
    859                     throw new SecurityException(
    860                             "Caller is not the current voice interaction service");
    861                 }
    862 
    863                 if (callback == null || recognitionConfig == null || bcp47Locale == null) {
    864                     throw new IllegalArgumentException("Illegal argument(s) in startRecognition");
    865                 }
    866             }
    867 
    868             int callingUid = UserHandle.getCallingUserId();
    869             final long caller = Binder.clearCallingIdentity();
    870             try {
    871                 KeyphraseSoundModel soundModel =
    872                         mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
    873                 if (soundModel == null
    874                         || soundModel.uuid == null
    875                         || soundModel.keyphrases == null) {
    876                     Slog.w(TAG, "No matching sound model found in startRecognition");
    877                     return SoundTriggerInternal.STATUS_ERROR;
    878                 } else {
    879                     // Regardless of the status of the start recognition, we need to make sure
    880                     // that we unload this model if needed later.
    881                     synchronized (this) {
    882                         mLoadedKeyphraseIds.add(keyphraseId);
    883                     }
    884                     return mSoundTriggerInternal.startRecognition(
    885                             keyphraseId, soundModel, callback, recognitionConfig);
    886                 }
    887             } finally {
    888                 Binder.restoreCallingIdentity(caller);
    889             }
    890         }
    891 
    892         @Override
    893         public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
    894                 IRecognitionStatusCallback callback) {
    895             // Allow the call if this is the current voice interaction service.
    896             synchronized (this) {
    897                 if (mImpl == null || mImpl.mService == null
    898                         || service == null || service.asBinder() != mImpl.mService.asBinder()) {
    899                     throw new SecurityException(
    900                             "Caller is not the current voice interaction service");
    901                 }
    902             }
    903 
    904             final long caller = Binder.clearCallingIdentity();
    905             try {
    906                 return mSoundTriggerInternal.stopRecognition(keyphraseId, callback);
    907             } finally {
    908                 Binder.restoreCallingIdentity(caller);
    909             }
    910         }
    911 
    912         private synchronized void unloadAllKeyphraseModels() {
    913             for (int keyphraseId : mLoadedKeyphraseIds) {
    914                 final long caller = Binder.clearCallingIdentity();
    915                 try {
    916                     int status = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId);
    917                     if (status != SoundTriggerInternal.STATUS_OK) {
    918                         Slog.w(TAG, "Failed to unload keyphrase " + keyphraseId + ":" + status);
    919                     }
    920                 } finally {
    921                     Binder.restoreCallingIdentity(caller);
    922                 }
    923             }
    924             mLoadedKeyphraseIds.clear();
    925         }
    926 
    927         @Override
    928         public ComponentName getActiveServiceComponentName() {
    929             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
    930             synchronized (this) {
    931                 return mImpl != null ? mImpl.mComponent : null;
    932             }
    933         }
    934 
    935         @Override
    936         public boolean showSessionForActiveService(Bundle args, int sourceFlags,
    937                 IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
    938             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
    939             synchronized (this) {
    940                 if (mImpl == null) {
    941                     Slog.w(TAG, "showSessionForActiveService without running voice interaction"
    942                             + "service");
    943                     return false;
    944                 }
    945                 final long caller = Binder.clearCallingIdentity();
    946                 try {
    947                     return mImpl.showSessionLocked(args,
    948                             sourceFlags
    949                                     | VoiceInteractionSession.SHOW_WITH_ASSIST
    950                                     | VoiceInteractionSession.SHOW_WITH_SCREENSHOT,
    951                             showCallback, activityToken);
    952                 } finally {
    953                     Binder.restoreCallingIdentity(caller);
    954                 }
    955             }
    956         }
    957 
    958         @Override
    959         public void hideCurrentSession() throws RemoteException {
    960             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
    961             synchronized (this) {
    962                 if (mImpl == null) {
    963                     return;
    964                 }
    965                 final long caller = Binder.clearCallingIdentity();
    966                 try {
    967                     if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
    968                         try {
    969                             mImpl.mActiveSession.mSession.closeSystemDialogs();
    970                         } catch (RemoteException e) {
    971                             Log.w(TAG, "Failed to call closeSystemDialogs", e);
    972                         }
    973                     }
    974                 } finally {
    975                     Binder.restoreCallingIdentity(caller);
    976                 }
    977             }
    978         }
    979 
    980         @Override
    981         public void launchVoiceAssistFromKeyguard() {
    982             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
    983             synchronized (this) {
    984                 if (mImpl == null) {
    985                     Slog.w(TAG, "launchVoiceAssistFromKeyguard without running voice interaction"
    986                             + "service");
    987                     return;
    988                 }
    989                 final long caller = Binder.clearCallingIdentity();
    990                 try {
    991                     mImpl.launchVoiceAssistFromKeyguard();
    992                 } finally {
    993                     Binder.restoreCallingIdentity(caller);
    994                 }
    995             }
    996         }
    997 
    998         @Override
    999         public boolean isSessionRunning() {
   1000             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
   1001             synchronized (this) {
   1002                 return mImpl != null && mImpl.mActiveSession != null;
   1003             }
   1004         }
   1005 
   1006         @Override
   1007         public boolean activeServiceSupportsAssist() {
   1008             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
   1009             synchronized (this) {
   1010                 return mImpl != null && mImpl.mInfo != null && mImpl.mInfo.getSupportsAssist();
   1011             }
   1012         }
   1013 
   1014         @Override
   1015         public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException {
   1016             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
   1017             synchronized (this) {
   1018                 return mImpl != null && mImpl.mInfo != null
   1019                         && mImpl.mInfo.getSupportsLaunchFromKeyguard();
   1020             }
   1021         }
   1022 
   1023         @Override
   1024         public void onLockscreenShown() {
   1025             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
   1026             synchronized (this) {
   1027                 if (mImpl == null) {
   1028                     return;
   1029                 }
   1030                 final long caller = Binder.clearCallingIdentity();
   1031                 try {
   1032                     if (mImpl.mActiveSession != null && mImpl.mActiveSession.mSession != null) {
   1033                         try {
   1034                             mImpl.mActiveSession.mSession.onLockscreenShown();
   1035                         } catch (RemoteException e) {
   1036                             Log.w(TAG, "Failed to call onLockscreenShown", e);
   1037                         }
   1038                     }
   1039                 } finally {
   1040                     Binder.restoreCallingIdentity(caller);
   1041                 }
   1042             }
   1043         }
   1044 
   1045         @Override
   1046         public void registerVoiceInteractionSessionListener(
   1047                 IVoiceInteractionSessionListener listener) {
   1048             enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
   1049             synchronized (this) {
   1050                 mVoiceInteractionSessionListeners.register(listener);
   1051             }
   1052         }
   1053 
   1054         public void onSessionShown() {
   1055             synchronized (this) {
   1056                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
   1057                 for (int i = 0; i < size; ++i) {
   1058                     final IVoiceInteractionSessionListener listener =
   1059                             mVoiceInteractionSessionListeners.getBroadcastItem(i);
   1060                     try {
   1061                         listener.onVoiceSessionShown();
   1062                     } catch (RemoteException e) {
   1063                         Slog.e(TAG, "Error delivering voice interaction open event.", e);
   1064                     }
   1065                 }
   1066                 mVoiceInteractionSessionListeners.finishBroadcast();
   1067             }
   1068         }
   1069 
   1070         public void onSessionHidden() {
   1071             synchronized (this) {
   1072                 final int size = mVoiceInteractionSessionListeners.beginBroadcast();
   1073                 for (int i = 0; i < size; ++i) {
   1074                     final IVoiceInteractionSessionListener listener =
   1075                             mVoiceInteractionSessionListeners.getBroadcastItem(i);
   1076                     try {
   1077                         listener.onVoiceSessionHidden();
   1078 
   1079                     } catch (RemoteException e) {
   1080                         Slog.e(TAG, "Error delivering voice interaction closed event.", e);
   1081                     }
   1082                 }
   1083                 mVoiceInteractionSessionListeners.finishBroadcast();
   1084             }
   1085         }
   1086 
   1087         @Override
   1088         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1089             if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
   1090                     != PackageManager.PERMISSION_GRANTED) {
   1091                 pw.println("Permission Denial: can't dump PowerManager from from pid="
   1092                         + Binder.getCallingPid()
   1093                         + ", uid=" + Binder.getCallingUid());
   1094                 return;
   1095             }
   1096             synchronized (this) {
   1097                 pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
   1098                 pw.println("  mEnableService: " + mEnableService);
   1099                 if (mImpl == null) {
   1100                     pw.println("  (No active implementation)");
   1101                     return;
   1102                 }
   1103                 mImpl.dumpLocked(fd, pw, args);
   1104             }
   1105             mSoundTriggerInternal.dump(fd, pw, args);
   1106         }
   1107 
   1108         private void enforceCallingPermission(String permission) {
   1109             if (mContext.checkCallingOrSelfPermission(permission)
   1110                     != PackageManager.PERMISSION_GRANTED) {
   1111                 throw new SecurityException("Caller does not hold the permission " + permission);
   1112             }
   1113         }
   1114 
   1115         class SettingsObserver extends ContentObserver {
   1116             SettingsObserver(Handler handler) {
   1117                 super(handler);
   1118                 ContentResolver resolver = mContext.getContentResolver();
   1119                 resolver.registerContentObserver(Settings.Secure.getUriFor(
   1120                         Settings.Secure.VOICE_INTERACTION_SERVICE), false, this,
   1121                         UserHandle.USER_ALL);
   1122             }
   1123 
   1124             @Override public void onChange(boolean selfChange) {
   1125                 synchronized (VoiceInteractionManagerServiceStub.this) {
   1126                     switchImplementationIfNeededLocked(false);
   1127                 }
   1128             }
   1129         }
   1130 
   1131         PackageMonitor mPackageMonitor = new PackageMonitor() {
   1132             @Override
   1133             public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
   1134                 if (DEBUG) Slog.d(TAG, "onHandleForceStop uid=" + uid + " doit=" + doit);
   1135 
   1136                 int userHandle = UserHandle.getUserId(uid);
   1137                 ComponentName curInteractor = getCurInteractor(userHandle);
   1138                 ComponentName curRecognizer = getCurRecognizer(userHandle);
   1139                 boolean hit = false;
   1140                 for (String pkg : packages) {
   1141                     if (curInteractor != null && pkg.equals(curInteractor.getPackageName())) {
   1142                         hit = true;
   1143                         break;
   1144                     } else if (curRecognizer != null
   1145                             && pkg.equals(curRecognizer.getPackageName())) {
   1146                         hit = true;
   1147                         break;
   1148                     }
   1149                 }
   1150                 if (hit && doit) {
   1151                     // The user is force stopping our current interactor/recognizer.
   1152                     // Clear the current settings and restore default state.
   1153                     synchronized (VoiceInteractionManagerServiceStub.this) {
   1154                         unloadAllKeyphraseModels();
   1155                         if (mImpl != null) {
   1156                             mImpl.shutdownLocked();
   1157                             mImpl = null;
   1158                         }
   1159                         setCurInteractor(null, userHandle);
   1160                         setCurRecognizer(null, userHandle);
   1161                         resetCurAssistant(userHandle);
   1162                         initForUser(userHandle);
   1163                         switchImplementationIfNeededLocked(true);
   1164                     }
   1165                 }
   1166                 return hit;
   1167             }
   1168 
   1169             @Override
   1170             public void onHandleUserStop(Intent intent, int userHandle) {
   1171             }
   1172 
   1173             @Override
   1174             public void onSomePackagesChanged() {
   1175                 int userHandle = getChangingUserId();
   1176                 if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);
   1177 
   1178                 synchronized (VoiceInteractionManagerServiceStub.this) {
   1179                     ComponentName curInteractor = getCurInteractor(userHandle);
   1180                     ComponentName curRecognizer = getCurRecognizer(userHandle);
   1181                     if (curRecognizer == null) {
   1182                         // Could a new recognizer appear when we don't have one pre-installed?
   1183                         if (anyPackagesAppearing()) {
   1184                             curRecognizer = findAvailRecognizer(null, userHandle);
   1185                             if (curRecognizer != null) {
   1186                                 setCurRecognizer(curRecognizer, userHandle);
   1187                             }
   1188                         }
   1189                         return;
   1190                     }
   1191 
   1192                     if (curInteractor != null) {
   1193                         int change = isPackageDisappearing(curInteractor.getPackageName());
   1194                         if (change == PACKAGE_PERMANENT_CHANGE) {
   1195                             // The currently set interactor is permanently gone; fall back to
   1196                             // the default config.
   1197                             setCurInteractor(null, userHandle);
   1198                             setCurRecognizer(null, userHandle);
   1199                             initForUser(userHandle);
   1200                             return;
   1201                         }
   1202 
   1203                         change = isPackageAppearing(curInteractor.getPackageName());
   1204                         if (change != PACKAGE_UNCHANGED) {
   1205                             // If current interactor is now appearing, for any reason, then
   1206                             // restart our connection with it.
   1207                             if (mImpl != null && curInteractor.getPackageName().equals(
   1208                                     mImpl.mComponent.getPackageName())) {
   1209                                 switchImplementationIfNeededLocked(true);
   1210                             }
   1211                         }
   1212                         return;
   1213                     }
   1214 
   1215                     // There is no interactor, so just deal with a simple recognizer.
   1216                     int change = isPackageDisappearing(curRecognizer.getPackageName());
   1217                     if (change == PACKAGE_PERMANENT_CHANGE
   1218                             || change == PACKAGE_TEMPORARY_CHANGE) {
   1219                         setCurRecognizer(findAvailRecognizer(null, userHandle), userHandle);
   1220 
   1221                     } else if (isPackageModified(curRecognizer.getPackageName())) {
   1222                         setCurRecognizer(findAvailRecognizer(curRecognizer.getPackageName(),
   1223                                 userHandle), userHandle);
   1224                     }
   1225                 }
   1226             }
   1227         };
   1228     }
   1229 }
   1230