21f1bd17b2
I am getting tired of writing package monitor code, realized this is missing in a number of places, and at this point it has gotten complicated enough that I don't think anyone actually does it 100% right so: Introducing PackageMonitor. Yes there are no Java docs. I am still playing around with just what this thing is to figure out what makes sense and how people will use it. It is being used to fix this bug for monitoring voice recognizers (integrating the code from the settings provider for setting an initial value), to replace the existing code for monitoring input methods (and fix the bug where we wouldn't remove an input method from the enabled list when it got uninstalled), to now monitor live wallpaper package changes (now allowing us to avoid reverting back to the default live wallpaper when the current one is updated!), and to monitor device admin changes. Also includes a fix so you can't uninstall an .apk that is currently enabled as a device admin. Also includes a fix where the default time zone was not initialized early enough which should fix issue #2455507 (Observed Google services frame work crash). In addition, this finally introduces a mechanism to determine if the "force stop" button should be enabled, with convenience in PackageMonitor for system services to handle it. All services have been updated to support this. There is also new infrastructure for reporting battery usage as an applicatin error report.
131 lines
4.6 KiB
Java
131 lines
4.6 KiB
Java
/*
|
|
* Copyright (C) 2010 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 com.android.server;
|
|
|
|
import com.android.internal.content.PackageMonitor;
|
|
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.pm.ResolveInfo;
|
|
import android.content.pm.ServiceInfo;
|
|
import android.content.pm.PackageManager.NameNotFoundException;
|
|
import android.os.Binder;
|
|
import android.provider.Settings;
|
|
import android.speech.RecognitionService;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
|
|
import java.util.List;
|
|
|
|
public class RecognitionManagerService extends Binder {
|
|
final static String TAG = "RecognitionManagerService";
|
|
|
|
final Context mContext;
|
|
final MyPackageMonitor mMonitor;
|
|
|
|
class MyPackageMonitor extends PackageMonitor {
|
|
public void onSomePackagesChanged() {
|
|
ComponentName comp = getCurRecognizer();
|
|
if (comp == null) {
|
|
if (anyPackagesAppearing()) {
|
|
comp = findAvailRecognizer(null);
|
|
if (comp != null) {
|
|
setCurRecognizer(comp);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
int change = isPackageDisappearing(comp.getPackageName());
|
|
if (change == PACKAGE_PERMANENT_CHANGE
|
|
|| change == PACKAGE_TEMPORARY_CHANGE) {
|
|
setCurRecognizer(findAvailRecognizer(null));
|
|
|
|
} else if (isPackageModified(comp.getPackageName())) {
|
|
setCurRecognizer(findAvailRecognizer(comp.getPackageName()));
|
|
}
|
|
}
|
|
}
|
|
|
|
RecognitionManagerService(Context context) {
|
|
mContext = context;
|
|
mMonitor = new MyPackageMonitor();
|
|
mMonitor.register(context, true);
|
|
}
|
|
|
|
public void systemReady() {
|
|
ComponentName comp = getCurRecognizer();
|
|
if (comp != null) {
|
|
// See if the current recognizer is no longer available.
|
|
try {
|
|
mContext.getPackageManager().getServiceInfo(comp, 0);
|
|
} catch (NameNotFoundException e) {
|
|
setCurRecognizer(null);
|
|
}
|
|
} else {
|
|
comp = findAvailRecognizer(null);
|
|
if (comp != null) {
|
|
setCurRecognizer(comp);
|
|
}
|
|
}
|
|
}
|
|
|
|
ComponentName findAvailRecognizer(String prefPackage) {
|
|
List<ResolveInfo> available =
|
|
mContext.getPackageManager().queryIntentServices(
|
|
new Intent(RecognitionService.SERVICE_INTERFACE), 0);
|
|
int numAvailable = available.size();
|
|
|
|
if (numAvailable == 0) {
|
|
Log.w(TAG, "no available voice recognition services found");
|
|
return null;
|
|
} else {
|
|
if (prefPackage != null) {
|
|
for (int i=0; i<numAvailable; i++) {
|
|
ServiceInfo serviceInfo = available.get(i).serviceInfo;
|
|
if (prefPackage.equals(serviceInfo.packageName)) {
|
|
return new ComponentName(serviceInfo.packageName, serviceInfo.name);
|
|
}
|
|
}
|
|
}
|
|
if (numAvailable > 1) {
|
|
Log.w(TAG, "more than one voice recognition service found, picking first");
|
|
}
|
|
|
|
ServiceInfo serviceInfo = available.get(0).serviceInfo;
|
|
return new ComponentName(serviceInfo.packageName, serviceInfo.name);
|
|
}
|
|
}
|
|
|
|
ComponentName getCurRecognizer() {
|
|
String curRecognizer = Settings.Secure.getString(
|
|
mContext.getContentResolver(),
|
|
Settings.Secure.VOICE_RECOGNITION_SERVICE);
|
|
if (TextUtils.isEmpty(curRecognizer)) {
|
|
return null;
|
|
}
|
|
return ComponentName.unflattenFromString(curRecognizer);
|
|
}
|
|
|
|
void setCurRecognizer(ComponentName comp) {
|
|
Settings.Secure.putString(mContext.getContentResolver(),
|
|
Settings.Secure.VOICE_RECOGNITION_SERVICE,
|
|
comp != null ? comp.flattenToShortString() : "");
|
|
}
|
|
}
|