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