diff options
| -rw-r--r-- | services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java | 139 |
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); |