VoiceInteractionManagerService.java revision c03c9167c2d9a1e22fb2b176b00a0524177fb037
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 17package com.android.server.voiceinteraction; 18 19import android.Manifest; 20import android.app.ActivityManager; 21import android.content.ComponentName; 22import android.content.ContentResolver; 23import android.content.Context; 24import android.content.Intent; 25import android.content.pm.PackageManager; 26import android.database.ContentObserver; 27import android.os.Binder; 28import android.os.Bundle; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.Parcel; 32import android.os.RemoteException; 33import android.os.UserHandle; 34import android.provider.Settings; 35import android.service.voice.IVoiceInteractionService; 36import android.service.voice.IVoiceInteractionSession; 37import android.util.Slog; 38import com.android.internal.app.IVoiceInteractionManagerService; 39import com.android.internal.app.IVoiceInteractor; 40import com.android.internal.content.PackageMonitor; 41import com.android.internal.os.BackgroundThread; 42import com.android.server.SystemService; 43import com.android.server.UiThread; 44 45import java.io.FileDescriptor; 46import java.io.PrintWriter; 47 48 49/** 50 * SystemService that publishes an IVoiceInteractionManagerService. 51 */ 52public class VoiceInteractionManagerService extends SystemService { 53 54 static final String TAG = "VoiceInteractionManagerService"; 55 56 final Context mContext; 57 final ContentResolver mResolver; 58 59 public VoiceInteractionManagerService(Context context) { 60 super(context); 61 mContext = context; 62 mResolver = context.getContentResolver(); 63 } 64 65 @Override 66 public void onStart() { 67 publishBinderService(Context.VOICE_INTERACTION_MANAGER_SERVICE, mServiceStub); 68 } 69 70 @Override 71 public void onBootPhase(int phase) { 72 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 73 mServiceStub.systemRunning(isSafeMode()); 74 } 75 } 76 77 @Override 78 public void onSwitchUser(int userHandle) { 79 mServiceStub.switchUser(userHandle); 80 } 81 82 // implementation entry point and binder service 83 private final VoiceInteractionManagerServiceStub mServiceStub 84 = new VoiceInteractionManagerServiceStub(); 85 86 class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub { 87 88 VoiceInteractionManagerServiceImpl mImpl; 89 90 private boolean mSafeMode; 91 private int mCurUser; 92 93 @Override 94 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 95 throws RemoteException { 96 try { 97 return super.onTransact(code, data, reply, flags); 98 } catch (RuntimeException e) { 99 // The activity manager only throws security exceptions, so let's 100 // log all others. 101 if (!(e instanceof SecurityException)) { 102 Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e); 103 } 104 throw e; 105 } 106 } 107 108 public void systemRunning(boolean safeMode) { 109 mSafeMode = safeMode; 110 111 mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(), 112 UserHandle.ALL, true); 113 new SettingsObserver(UiThread.getHandler()); 114 115 synchronized (this) { 116 mCurUser = ActivityManager.getCurrentUser(); 117 switchImplementationIfNeededLocked(false); 118 } 119 } 120 121 public void switchUser(int userHandle) { 122 synchronized (this) { 123 mCurUser = userHandle; 124 switchImplementationIfNeededLocked(false); 125 } 126 } 127 128 void switchImplementationIfNeededLocked(boolean force) { 129 if (!mSafeMode) { 130 String curService = Settings.Secure.getStringForUser( 131 mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser); 132 ComponentName serviceComponent = null; 133 if (curService != null && !curService.isEmpty()) { 134 try { 135 serviceComponent = ComponentName.unflattenFromString(curService); 136 } catch (RuntimeException e) { 137 Slog.wtf(TAG, "Bad voice interaction service name " + curService, e); 138 serviceComponent = null; 139 } 140 } 141 if (force || mImpl == null || mImpl.mUser != mCurUser 142 || !mImpl.mComponent.equals(serviceComponent)) { 143 if (mImpl != null) { 144 mImpl.shutdownLocked(); 145 } 146 if (serviceComponent != null) { 147 mImpl = new VoiceInteractionManagerServiceImpl(mContext, 148 UiThread.getHandler(), this, mCurUser, serviceComponent); 149 mImpl.startLocked(); 150 } else { 151 mImpl = null; 152 } 153 } 154 } 155 } 156 157 @Override 158 public void startSession(IVoiceInteractionService service, Bundle args) { 159 synchronized (this) { 160 if (mImpl == null || mImpl.mService == null 161 || service.asBinder() != mImpl.mService.asBinder()) { 162 throw new SecurityException( 163 "Caller is not the current voice interaction service"); 164 } 165 final int callingPid = Binder.getCallingPid(); 166 final int callingUid = Binder.getCallingUid(); 167 final long caller = Binder.clearCallingIdentity(); 168 try { 169 mImpl.startSessionLocked(callingPid, callingUid, args); 170 } finally { 171 Binder.restoreCallingIdentity(caller); 172 } 173 } 174 } 175 176 @Override 177 public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session, 178 IVoiceInteractor interactor) { 179 synchronized (this) { 180 if (mImpl == null) { 181 throw new SecurityException( 182 "deliverNewSession without running voice interaction service"); 183 } 184 final int callingPid = Binder.getCallingPid(); 185 final int callingUid = Binder.getCallingUid(); 186 final long caller = Binder.clearCallingIdentity(); 187 try { 188 return mImpl.deliverNewSessionLocked(callingPid, callingUid, token, session, 189 interactor); 190 } finally { 191 Binder.restoreCallingIdentity(caller); 192 } 193 } 194 } 195 196 @Override 197 public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) { 198 synchronized (this) { 199 if (mImpl == null) { 200 Slog.w(TAG, "startVoiceActivity without running voice interaction service"); 201 return ActivityManager.START_CANCELED; 202 } 203 final int callingPid = Binder.getCallingPid(); 204 final int callingUid = Binder.getCallingUid(); 205 final long caller = Binder.clearCallingIdentity(); 206 try { 207 return mImpl.startVoiceActivityLocked(callingPid, callingUid, token, 208 intent, resolvedType); 209 } finally { 210 Binder.restoreCallingIdentity(caller); 211 } 212 } 213 } 214 215 @Override 216 public void finish(IBinder token) { 217 synchronized (this) { 218 if (mImpl == null) { 219 Slog.w(TAG, "finish without running voice interaction service"); 220 return; 221 } 222 final int callingPid = Binder.getCallingPid(); 223 final int callingUid = Binder.getCallingUid(); 224 final long caller = Binder.clearCallingIdentity(); 225 try { 226 mImpl.finishLocked(callingPid, callingUid, token); 227 } finally { 228 Binder.restoreCallingIdentity(caller); 229 } 230 } 231 } 232 233 @Override 234 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 235 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 236 != PackageManager.PERMISSION_GRANTED) { 237 pw.println("Permission Denial: can't dump PowerManager from from pid=" 238 + Binder.getCallingPid() 239 + ", uid=" + Binder.getCallingUid()); 240 return; 241 } 242 synchronized (this) { 243 pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)\n"); 244 if (mImpl == null) { 245 pw.println(" (No active implementation)"); 246 return; 247 } 248 mImpl.dumpLocked(fd, pw, args); 249 } 250 } 251 252 class SettingsObserver extends ContentObserver { 253 SettingsObserver(Handler handler) { 254 super(handler); 255 ContentResolver resolver = mContext.getContentResolver(); 256 resolver.registerContentObserver(Settings.Secure.getUriFor( 257 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this); 258 } 259 260 @Override public void onChange(boolean selfChange) { 261 synchronized (VoiceInteractionManagerServiceStub.this) { 262 switchImplementationIfNeededLocked(false); 263 } 264 } 265 } 266 267 PackageMonitor mPackageMonitor = new PackageMonitor() { 268 @Override 269 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { 270 return super.onHandleForceStop(intent, packages, uid, doit); 271 } 272 273 @Override 274 public void onHandleUserStop(Intent intent, int userHandle) { 275 } 276 277 @Override 278 public void onPackageDisappeared(String packageName, int reason) { 279 } 280 281 @Override 282 public void onPackageAppeared(String packageName, int reason) { 283 if (mImpl != null && packageName.equals(mImpl.mComponent.getPackageName())) { 284 switchImplementationIfNeededLocked(true); 285 } 286 } 287 288 @Override 289 public void onPackageModified(String packageName) { 290 } 291 292 @Override 293 public void onSomePackagesChanged() { 294 } 295 }; 296 } 297} 298