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

This commit is contained in:
Joanne Chung
2021-06-02 10:33:13 +00:00
committed by Android (Google) Code Review

View File

@@ -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);