am 68f35ec2: am dbec91c0: Implement issue #16330060: Inform ActivityManager about WebView...
* commit '68f35ec2d2f9950f57afa9900f16a3b29a8d55b0': Implement issue #16330060: Inform ActivityManager about WebView...
This commit is contained in:
@@ -1819,7 +1819,29 @@ public class ActivityManager {
|
||||
* actively running code.
|
||||
*/
|
||||
public static final int IMPORTANCE_EMPTY = 500;
|
||||
|
||||
|
||||
/**
|
||||
* Constant for {@link #importance}: this process does not exist.
|
||||
*/
|
||||
public static final int IMPORTANCE_GONE = 1000;
|
||||
|
||||
/** @hide */
|
||||
public static int procStateToImportance(int procState) {
|
||||
if (procState >= ActivityManager.PROCESS_STATE_HOME) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
|
||||
} else if (procState >= ActivityManager.PROCESS_STATE_SERVICE) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
|
||||
} else if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
|
||||
} else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
|
||||
} else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
|
||||
} else {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The relative importance level that the system places on this
|
||||
* process. May be one of {@link #IMPORTANCE_FOREGROUND},
|
||||
|
||||
@@ -1465,7 +1465,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case ADD_PACKAGE_DEPENDENCY_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
String packageName = data.readString();
|
||||
addPackageDependency(packageName);
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
|
||||
case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
String pkg = data.readString();
|
||||
@@ -1475,7 +1483,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
||||
reply.writeNoException();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
case CLOSE_SYSTEM_DIALOGS_TRANSACTION: {
|
||||
data.enforceInterface(IActivityManager.descriptor);
|
||||
String reason = data.readString();
|
||||
@@ -4050,7 +4058,18 @@ class ActivityManagerProxy implements IActivityManager
|
||||
reply.recycle();
|
||||
data.recycle();
|
||||
}
|
||||
|
||||
|
||||
public void addPackageDependency(String packageName) throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
Parcel reply = Parcel.obtain();
|
||||
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||
data.writeString(packageName);
|
||||
mRemote.transact(ADD_PACKAGE_DEPENDENCY_TRANSACTION, data, reply, 0);
|
||||
reply.readException();
|
||||
data.recycle();
|
||||
reply.recycle();
|
||||
}
|
||||
|
||||
public void killApplicationWithAppId(String pkg, int appid, String reason)
|
||||
throws RemoteException {
|
||||
Parcel data = Parcel.obtain();
|
||||
|
||||
@@ -1684,6 +1684,7 @@ public final class ActivityThread {
|
||||
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
|
||||
? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
|
||||
: true);
|
||||
boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
|
||||
if ((flags&(Context.CONTEXT_INCLUDE_CODE
|
||||
|Context.CONTEXT_IGNORE_SECURITY))
|
||||
== Context.CONTEXT_INCLUDE_CODE) {
|
||||
@@ -1698,12 +1699,13 @@ public final class ActivityThread {
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
}
|
||||
return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
|
||||
return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
|
||||
registerPackage);
|
||||
}
|
||||
|
||||
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
|
||||
CompatibilityInfo compatInfo) {
|
||||
return getPackageInfo(ai, compatInfo, null, false, true);
|
||||
return getPackageInfo(ai, compatInfo, null, false, true, false);
|
||||
}
|
||||
|
||||
public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
|
||||
@@ -1719,7 +1721,8 @@ public final class ActivityThread {
|
||||
}
|
||||
|
||||
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
|
||||
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
|
||||
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
|
||||
boolean registerPackage) {
|
||||
synchronized (mResourcesManager) {
|
||||
WeakReference<LoadedApk> ref;
|
||||
if (includeCode) {
|
||||
@@ -1738,7 +1741,7 @@ public final class ActivityThread {
|
||||
packageInfo =
|
||||
new LoadedApk(this, aInfo, compatInfo, baseLoader,
|
||||
securityViolation, includeCode &&
|
||||
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
|
||||
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
|
||||
if (includeCode) {
|
||||
mPackages.put(aInfo.packageName,
|
||||
new WeakReference<LoadedApk>(packageInfo));
|
||||
@@ -4394,7 +4397,7 @@ public final class ActivityThread {
|
||||
instrApp.dataDir = ii.dataDir;
|
||||
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
|
||||
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
|
||||
appContext.getClassLoader(), false, true);
|
||||
appContext.getClassLoader(), false, true, false);
|
||||
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
|
||||
|
||||
try {
|
||||
|
||||
150
core/java/android/app/AppImportanceMonitor.java
Normal file
150
core/java/android/app/AppImportanceMonitor.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper for monitoring the current importance of applications.
|
||||
* @hide
|
||||
*/
|
||||
public class AppImportanceMonitor {
|
||||
final Context mContext;
|
||||
|
||||
final SparseArray<AppEntry> mApps = new SparseArray<>();
|
||||
|
||||
static class AppEntry {
|
||||
final int uid;
|
||||
final SparseArray<Integer> procs = new SparseArray<>(1);
|
||||
int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
|
||||
|
||||
AppEntry(int _uid) {
|
||||
uid = _uid;
|
||||
}
|
||||
}
|
||||
|
||||
final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
|
||||
@Override
|
||||
public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessStateChanged(int pid, int uid, int procState) {
|
||||
synchronized (mApps) {
|
||||
updateImportanceLocked(pid, uid,
|
||||
ActivityManager.RunningAppProcessInfo.procStateToImportance(procState),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessDied(int pid, int uid) {
|
||||
synchronized (mApps) {
|
||||
updateImportanceLocked(pid, uid,
|
||||
ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static final int MSG_UPDATE = 1;
|
||||
|
||||
final Handler mHandler;
|
||||
|
||||
public AppImportanceMonitor(Context context, Looper looper) {
|
||||
mContext = context;
|
||||
mHandler = new Handler(looper) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_UPDATE:
|
||||
onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
try {
|
||||
ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
|
||||
if (apps != null) {
|
||||
for (int i=0; i<apps.size(); i++) {
|
||||
ActivityManager.RunningAppProcessInfo app = apps.get(i);
|
||||
updateImportanceLocked(app.uid, app.pid, app.importance, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getImportance(int uid) {
|
||||
AppEntry ent = mApps.get(uid);
|
||||
if (ent == null) {
|
||||
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
|
||||
}
|
||||
return ent.importance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report when an app's importance changed. Called on looper given to constructor.
|
||||
*/
|
||||
public void onImportanceChanged(int uid, int importance, int oldImportance) {
|
||||
}
|
||||
|
||||
void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) {
|
||||
AppEntry ent = mApps.get(uid);
|
||||
if (ent == null) {
|
||||
ent = new AppEntry(uid);
|
||||
mApps.put(uid, ent);
|
||||
}
|
||||
if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
|
||||
ent.procs.remove(pid);
|
||||
} else {
|
||||
ent.procs.put(pid, importance);
|
||||
}
|
||||
updateImportanceLocked(ent, repChange);
|
||||
}
|
||||
|
||||
void updateImportanceLocked(AppEntry ent, boolean repChange) {
|
||||
int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
|
||||
for (int i=0; i<ent.procs.size(); i++) {
|
||||
int procImp = ent.procs.valueAt(i);
|
||||
if (procImp < appImp) {
|
||||
appImp = procImp;
|
||||
}
|
||||
}
|
||||
if (appImp != ent.importance) {
|
||||
int impCode = appImp | (ent.importance<<16);
|
||||
ent.importance = appImp;
|
||||
if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
|
||||
mApps.remove(ent.uid);
|
||||
}
|
||||
if (repChange) {
|
||||
mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2097,7 +2097,7 @@ class ContextImpl extends Context {
|
||||
}
|
||||
|
||||
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
|
||||
flags, user.getIdentifier());
|
||||
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
|
||||
if (pi != null) {
|
||||
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
|
||||
user, restricted, mDisplay, mOverrideConfiguration);
|
||||
|
||||
@@ -294,7 +294,9 @@ public interface IActivityManager extends IInterface {
|
||||
|
||||
public void stopAppSwitches() throws RemoteException;
|
||||
public void resumeAppSwitches() throws RemoteException;
|
||||
|
||||
|
||||
public void addPackageDependency(String packageName) throws RemoteException;
|
||||
|
||||
public void killApplicationWithAppId(String pkg, int appid, String reason)
|
||||
throws RemoteException;
|
||||
|
||||
@@ -640,7 +642,7 @@ public interface IActivityManager extends IInterface {
|
||||
int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
|
||||
int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
|
||||
int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
|
||||
int ___AVAILABLE_2___ = IBinder.FIRST_CALL_TRANSACTION+94;
|
||||
int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
|
||||
int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
|
||||
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
|
||||
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
|
||||
|
||||
@@ -93,6 +93,7 @@ public final class LoadedApk {
|
||||
private final ClassLoader mBaseClassLoader;
|
||||
private final boolean mSecurityViolation;
|
||||
private final boolean mIncludeCode;
|
||||
private final boolean mRegisterPackage;
|
||||
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
|
||||
Resources mResources;
|
||||
private ClassLoader mClassLoader;
|
||||
@@ -121,7 +122,7 @@ public final class LoadedApk {
|
||||
*/
|
||||
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
|
||||
CompatibilityInfo compatInfo, ClassLoader baseLoader,
|
||||
boolean securityViolation, boolean includeCode) {
|
||||
boolean securityViolation, boolean includeCode, boolean registerPackage) {
|
||||
final int myUid = Process.myUid();
|
||||
aInfo = adjustNativeLibraryPaths(aInfo);
|
||||
|
||||
@@ -144,6 +145,7 @@ public final class LoadedApk {
|
||||
mBaseClassLoader = baseLoader;
|
||||
mSecurityViolation = securityViolation;
|
||||
mIncludeCode = includeCode;
|
||||
mRegisterPackage = registerPackage;
|
||||
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
|
||||
}
|
||||
|
||||
@@ -189,6 +191,7 @@ public final class LoadedApk {
|
||||
mBaseClassLoader = null;
|
||||
mSecurityViolation = false;
|
||||
mIncludeCode = true;
|
||||
mRegisterPackage = false;
|
||||
mClassLoader = ClassLoader.getSystemClassLoader();
|
||||
mResources = Resources.getSystem();
|
||||
}
|
||||
@@ -272,6 +275,13 @@ public final class LoadedApk {
|
||||
final ArrayList<String> zipPaths = new ArrayList<>();
|
||||
final ArrayList<String> libPaths = new ArrayList<>();
|
||||
|
||||
if (mRegisterPackage) {
|
||||
try {
|
||||
ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
zipPaths.add(mAppDir);
|
||||
if (mSplitAppDirs != null) {
|
||||
Collections.addAll(zipPaths, mSplitAppDirs);
|
||||
|
||||
@@ -2475,11 +2475,11 @@ public abstract class Context {
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a {@link
|
||||
* android.net.ethernet.EthernetManager} for handling management of
|
||||
* android.net.EthernetManager} for handling management of
|
||||
* Ethernet access.
|
||||
*
|
||||
* @see #getSystemService
|
||||
* @see android.net.ethernet.EthernetManager
|
||||
* @see android.net.EthernetManager
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -3250,6 +3250,12 @@ public abstract class Context {
|
||||
*/
|
||||
public static final int CONTEXT_RESTRICTED = 0x00000004;
|
||||
|
||||
/**
|
||||
* @hide Used to indicate we should tell the activity manager about the process
|
||||
* loading this code.
|
||||
*/
|
||||
public static final int CONTEXT_REGISTER_PACKAGE = 0x40000000;
|
||||
|
||||
/**
|
||||
* Return a new Context object for the given application name. This
|
||||
* Context is the same as what the named application gets when it is
|
||||
|
||||
@@ -20,4 +20,5 @@ package android.service.voice;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IVoiceInteractionService {
|
||||
void ready();
|
||||
}
|
||||
|
||||
@@ -18,15 +18,19 @@ package android.service.voice;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
|
||||
import android.hardware.soundtrigger.SoundTriggerHelper;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
|
||||
import android.provider.Settings;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.IVoiceInteractionManagerService;
|
||||
|
||||
@@ -64,14 +68,58 @@ public class VoiceInteractionService extends Service {
|
||||
public static final String SERVICE_META_DATA = "android.voice_interaction";
|
||||
|
||||
IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
|
||||
@Override public void ready() {
|
||||
mHandler.sendEmptyMessage(MSG_READY);
|
||||
}
|
||||
};
|
||||
|
||||
MyHandler mHandler;
|
||||
|
||||
IVoiceInteractionManagerService mSystemService;
|
||||
|
||||
private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
|
||||
private SoundTriggerHelper mSoundTriggerHelper;
|
||||
|
||||
static final int MSG_READY = 1;
|
||||
|
||||
class MyHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_READY:
|
||||
onReady();
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given service component is the currently active
|
||||
* VoiceInteractionService.
|
||||
*/
|
||||
public static boolean isActiveService(Context context, ComponentName service) {
|
||||
String cur = Settings.Secure.getString(context.getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE);
|
||||
if (cur == null || cur.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
ComponentName curComp = ComponentName.unflattenFromString(cur);
|
||||
if (curComp == null) {
|
||||
return false;
|
||||
}
|
||||
return curComp.equals(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the execution of a new {@link android.service.voice.VoiceInteractionSession}.
|
||||
* @param args Arbitrary arguments that will be propagated to the session.
|
||||
*/
|
||||
public void startSession(Bundle args) {
|
||||
if (mSystemService == null) {
|
||||
throw new IllegalStateException("Not available until onReady() is called");
|
||||
}
|
||||
try {
|
||||
mSystemService.startSession(mInterface, args);
|
||||
} catch (RemoteException e) {
|
||||
@@ -81,10 +129,7 @@ public class VoiceInteractionService extends Service {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
|
||||
mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager());
|
||||
mSoundTriggerHelper = new SoundTriggerHelper();
|
||||
mHandler = new MyHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,6 +140,19 @@ public class VoiceInteractionService extends Service {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during service initialization to tell you when the system is ready
|
||||
* to receive interaction from it. You should generally do initialization here
|
||||
* rather than in {@link #onCreate()}. Methods such as {@link #startSession}
|
||||
* and {@link #getAlwaysOnHotwordDetector} will not be operational until this point.
|
||||
*/
|
||||
public void onReady() {
|
||||
mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
|
||||
mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager());
|
||||
mSoundTriggerHelper = new SoundTriggerHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyphrase The keyphrase that's being used, for example "Hello Android".
|
||||
* @param locale The locale for which the enrollment needs to be performed.
|
||||
@@ -104,6 +162,11 @@ public class VoiceInteractionService extends Service {
|
||||
*/
|
||||
public final AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(
|
||||
String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) {
|
||||
if (mSystemService == null) {
|
||||
throw new IllegalStateException("Not available until onReady() is called");
|
||||
}
|
||||
// TODO: Cache instances and return the same one instead of creating a new interactor
|
||||
// for the same keyphrase/locale combination.
|
||||
return new AlwaysOnHotwordDetector(keyphrase, locale, callback,
|
||||
mKeyphraseEnrollmentInfo, mSoundTriggerHelper, mInterface, mSystemService);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public class VoiceInteractionServiceInfo {
|
||||
|
||||
private ServiceInfo mServiceInfo;
|
||||
private String mSessionService;
|
||||
private String mRecognitionService;
|
||||
private String mSettingsActivity;
|
||||
|
||||
public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
|
||||
@@ -82,6 +83,8 @@ public class VoiceInteractionServiceInfo {
|
||||
com.android.internal.R.styleable.VoiceInteractionService);
|
||||
mSessionService = array.getString(
|
||||
com.android.internal.R.styleable.VoiceInteractionService_sessionService);
|
||||
mRecognitionService = array.getString(
|
||||
com.android.internal.R.styleable.VoiceInteractionService_recognitionService);
|
||||
mSettingsActivity = array.getString(
|
||||
com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
|
||||
array.recycle();
|
||||
@@ -119,6 +122,10 @@ public class VoiceInteractionServiceInfo {
|
||||
return mSessionService;
|
||||
}
|
||||
|
||||
public String getRecognitionService() {
|
||||
return mRecognitionService;
|
||||
}
|
||||
|
||||
public String getSettingsActivity() {
|
||||
return mSettingsActivity;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user