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