summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java139
1 files changed, 139 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 753b42b24556..0f37450c24c9 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -25,6 +25,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
@@ -59,6 +61,7 @@ import android.view.textclassifier.TextLinks;
import android.view.textclassifier.TextSelection;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.FunctionalUtils.ThrowingConsumer;
@@ -110,6 +113,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
try {
publishBinderService(Context.TEXT_CLASSIFICATION_SERVICE, mManagerService);
mManagerService.startListenSettings();
+ mManagerService.startTrackingPackageChanges();
} catch (Throwable t) {
// Starting this service is not critical to the running of this device and should
// therefore not crash the device. If it fails, log the error and continue.
@@ -119,11 +123,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onUserStarting(@NonNull TargetUser user) {
+ updatePackageStateForUser(user.getUserIdentifier());
processAnyPendingWork(user.getUserIdentifier());
}
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
+ // refresh if we failed earlier due to locked encrypted user
+ updatePackageStateForUser(user.getUserIdentifier());
// Rebind if we failed earlier due to locked encrypted user
processAnyPendingWork(user.getUserIdentifier());
}
@@ -134,6 +141,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
}
+ private void updatePackageStateForUser(int userId) {
+ synchronized (mManagerService.mLock) {
+ // Update the cached disable status, the TextClassfier may not be direct boot aware,
+ // we should update the disable status after user unlock
+ mManagerService.getUserStateLocked(userId).updatePackageStateLocked();
+ }
+ }
+
@Override
public void onUserStopping(@NonNull TargetUser user) {
int userId = user.getUserIdentifier();
@@ -160,6 +175,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
private final String mDefaultTextClassifierPackage;
@Nullable
private final String mSystemTextClassifierPackage;
+ // TODO: consider using device config to control it.
+ private boolean DEBUG = false;
private TextClassificationManagerService(Context context) {
mContext = Objects.requireNonNull(context);
@@ -176,6 +193,46 @@ public final class TextClassificationManagerService extends ITextClassifierServi
mSettingsListener.registerObserver();
}
+ void startTrackingPackageChanges() {
+ final PackageMonitor monitor = new PackageMonitor() {
+
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ notifyPackageInstallStatusChange(packageName, /* installed*/ true);
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ notifyPackageInstallStatusChange(packageName, /* installed= */ false);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final UserState userState = getUserStateLocked(userId);
+ final ServiceState serviceState = userState.getServiceStateLocked(packageName);
+ if (serviceState != null) {
+ serviceState.onPackageModifiedLocked();
+ }
+ }
+ }
+
+ private void notifyPackageInstallStatusChange(String packageName, boolean installed) {
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final UserState userState = getUserStateLocked(userId);
+ final ServiceState serviceState = userState.getServiceStateLocked(packageName);
+ if (serviceState != null) {
+ serviceState.onPackageInstallStatusChangeLocked(installed);
+ }
+ }
+ }
+ };
+
+ monitor.register(mContext, null, UserHandle.ALL, true);
+ }
+
@Override
public void onConnectedStateChanged(@ConnectionState int connected) {
}
@@ -452,6 +509,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
if (serviceState == null) {
Slog.d(LOG_TAG, "No configured system TextClassifierService");
callback.onFailure();
+ } else if (!serviceState.isInstalledLocked() || !serviceState.isEnabledLocked()) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG,
+ serviceState.mPackageName + " is not available in user " + userId
+ + ". Installed: " + serviceState.isInstalledLocked()
+ + ", enabled:" + serviceState.isEnabledLocked());
+ }
+ callback.onFailure();
} else if (attemptToBind && !serviceState.bindLocked()) {
Slog.d(LOG_TAG, "Unable to bind TextClassifierService at " + methodName);
callback.onFailure();
@@ -761,6 +826,24 @@ public final class TextClassificationManagerService extends ITextClassifierServi
return serviceStates;
}
+ @GuardedBy("mLock")
+ @Nullable
+ private ServiceState getServiceStateLocked(String packageName) {
+ for (ServiceState serviceState : getAllServiceStatesLocked()) {
+ if (serviceState.mPackageName.equals(packageName)) {
+ return serviceState;
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy("mLock")
+ private void updatePackageStateLocked() {
+ for (ServiceState serviceState : getAllServiceStatesLocked()) {
+ serviceState.updatePackageStateLocked();
+ }
+ }
+
void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.increaseIndent();
@@ -814,6 +897,10 @@ public final class TextClassificationManagerService extends ITextClassifierServi
ComponentName mBoundComponentName = null;
@GuardedBy("mLock")
int mBoundServiceUid = Process.INVALID_UID;
+ @GuardedBy("mLock")
+ boolean mInstalled;
+ @GuardedBy("mLock")
+ boolean mEnabled;
private ServiceState(
@UserIdInt int userId, @NonNull String packageName, boolean isTrusted) {
@@ -822,6 +909,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
mConnection = new TextClassifierServiceConnection(mUserId);
mIsTrusted = isTrusted;
mBindServiceFlags = createBindServiceFlags(packageName);
+ mInstalled = isPackageInstalledForUser();
+ mEnabled = isServiceEnabledForUser();
}
@Context.BindServiceFlags
@@ -833,6 +922,54 @@ public final class TextClassificationManagerService extends ITextClassifierServi
return flags;
}
+ private boolean isPackageInstalledForUser() {
+ try {
+ PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.getPackageInfoAsUser(mPackageName, 0, mUserId) != null;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private boolean isServiceEnabledForUser() {
+ PackageManager packageManager = mContext.getPackageManager();
+ Intent intent = new Intent(TextClassifierService.SERVICE_INTERFACE);
+ intent.setPackage(mPackageName);
+ ResolveInfo resolveInfo = packageManager.resolveServiceAsUser(intent,
+ PackageManager.GET_SERVICES, mUserId);
+ ServiceInfo serviceInfo = resolveInfo == null ? null : resolveInfo.serviceInfo;
+ return serviceInfo != null;
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void onPackageInstallStatusChangeLocked(boolean installed) {
+ mInstalled = installed;
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void onPackageModifiedLocked() {
+ mEnabled = isServiceEnabledForUser();
+ }
+
+ @GuardedBy("mLock")
+ @NonNull
+ private void updatePackageStateLocked() {
+ mInstalled = isPackageInstalledForUser();
+ mEnabled = isServiceEnabledForUser();
+ }
+
+ @GuardedBy("mLock")
+ boolean isInstalledLocked() {
+ return mInstalled;
+ }
+
+ @GuardedBy("mLock")
+ boolean isEnabledLocked() {
+ return mEnabled;
+ }
+
@GuardedBy("mLock")
boolean isBoundLocked() {
return mService != null;
@@ -923,6 +1060,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
pw.printPair("userId", mUserId);
synchronized (mLock) {
pw.printPair("packageName", mPackageName);
+ pw.printPair("installed", mInstalled);
+ pw.printPair("enabled", mEnabled);
pw.printPair("boundComponentName", mBoundComponentName);
pw.printPair("isTrusted", mIsTrusted);
pw.printPair("bindServiceFlags", mBindServiceFlags);