diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 25ea12b1c341a..8a42ddfdc19d1 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -70,6 +70,7 @@ import android.provider.Settings; import android.service.contentcapture.ActivityEvent.ActivityEventType; import android.service.contentcapture.IDataShareCallback; import android.service.contentcapture.IDataShareReadAdapter; +import android.service.voice.VoiceInteractionManagerInternal; import android.util.ArraySet; import android.util.LocalLog; import android.util.Pair; @@ -302,6 +303,37 @@ public final class ContentCaptureManagerService extends || super.isDisabledLocked(userId); } + @Override + protected void assertCalledByPackageOwner(@NonNull String packageName) { + try { + super.assertCalledByPackageOwner(packageName); + } catch (SecurityException e) { + final int callingUid = Binder.getCallingUid(); + + VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity + hotwordDetectionServiceIdentity = + LocalServices.getService(VoiceInteractionManagerInternal.class) + .getHotwordDetectionServiceIdentity(); + + if (callingUid != hotwordDetectionServiceIdentity.getIsolatedUid()) { + super.assertCalledByPackageOwner(packageName); + return; + } + + final String[] packages = + getContext() + .getPackageManager() + .getPackagesForUid(hotwordDetectionServiceIdentity.getOwnerUid()); + if (packages != null) { + for (String candidate : packages) { + if (packageName.equals(candidate)) return; // Found it + } + } + + throw e; + } + } + private boolean isDisabledBySettingsLocked(@UserIdInt int userId) { return mDisabledBySettings != null && mDisabledBySettings.get(userId); } diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index 225a8d48114bb..904def0af2cf2 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -57,6 +57,7 @@ import android.service.contentcapture.FlushMetrics; import android.service.contentcapture.IContentCaptureServiceCallback; import android.service.contentcapture.IDataShareCallback; import android.service.contentcapture.SnapshotData; +import android.service.voice.VoiceInteractionManagerInternal; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; @@ -415,12 +416,25 @@ final class ContentCapturePerUserService } if (callingUid != packageUid && !LocalServices.getService(ActivityManagerInternal.class) .hasRunningActivity(callingUid, packageName)) { - final String[] packages = pm.getPackagesForUid(callingUid); - final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; - Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid - + ") passed package (" + packageName + ") owned by UID " + packageUid); - throw new SecurityException("Invalid package: " + packageName); + VoiceInteractionManagerInternal.HotwordDetectionServiceIdentity + hotwordDetectionServiceIdentity = + LocalServices.getService(VoiceInteractionManagerInternal.class) + .getHotwordDetectionServiceIdentity(); + + boolean isHotwordDetectionServiceCall = + hotwordDetectionServiceIdentity != null + && callingUid == hotwordDetectionServiceIdentity.getIsolatedUid() + && packageUid == hotwordDetectionServiceIdentity.getOwnerUid(); + + if (!isHotwordDetectionServiceCall) { + final String[] packages = pm.getPackagesForUid(callingUid); + final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; + Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid + + ") passed package (" + packageName + ") owned by UID " + packageUid); + + throw new SecurityException("Invalid package: " + packageName); + } } } diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java index 016c5ed36f5f8..14616754e1604 100644 --- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java +++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java @@ -744,7 +744,7 @@ public abstract class AbstractMasterSystemService