Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 282d357f authored by Joanne Chung's avatar Joanne Chung Committed by Automerger Merge Worker
Browse files

Merge "Do not bind TextClassifierService if the packge doesn't install." into...

Merge "Do not bind TextClassifierService if the packge doesn't install." into sc-dev am: 4575821b am: 438ad56f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14674302

Change-Id: Ia5b5b816c904fb2912d2cdbfb30ece3fb10603fb
parents 10ad06d0 438ad56f
Loading
Loading
Loading
Loading
+139 −0
Original line number Diff line number Diff line
@@ -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);