diff -wurN a/frameworks/base/core/java/android/app/compat/sn00x/AndroidAutoHelper.java b/frameworks/base/core/java/android/app/compat/sn00x/AndroidAutoHelper.java --- a/frameworks/base/core/java/android/app/compat/sn00x/AndroidAutoHelper.java 1970-01-01 01:00:00.000000000 +0100 +++ b/frameworks/base/core/java/android/app/compat/sn00x/AndroidAutoHelper.java 2023-08-30 14:39:42.402352779 +0200 @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.compat.sn00x; + +import android.app.ActivityThread; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.content.pm.SigningDetails; +import android.content.pm.SigningInfo; +import android.os.Build; +import android.os.RemoteException; +import android.provider.Settings; +import android.util.ArraySet; +import android.util.Log; +import android.util.PackageUtils; + +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * This class provides helpers for Android Auto, screen2auto and media app compatibility. + * + * @hide + */ +public final class AndroidAutoHelper { + private static final String PACKAGE_ANDROIDAUTO = "com.google.android.projection.gearhead"; + private static final Set SIGNATURES_ANDROIDAUTO = new ArraySet<>( + Arrays.asList( + "FDB00C43DBDE8B51CB312AA81D3B5FA17713ADB94B28F598D77F8EB89DACEEDF" // CN=gearhead, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US + ) + ); + private static final String PACKAGE_SCREEN2AUTO = "new.package.name.s2a"; // replace with new package name of Screen2Auto + private static final Set SIGNATURES_SCREEN2AUTO = new ArraySet<>( + Arrays.asList( + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" // replace with sha256 hash of signing certificate + ) + ); + private static final List PACKAGES_MEDIAAPPS = Arrays.asList( + "com.netflix.mediaclient", + "com.amazon.avod.thirdpartyclient", + "com.disney.disneyplus", + "com.spotify.music" + ); + + private static boolean androidAutoActive = false; + private static boolean screenCaptureActive = false; + + // Define additionally allowed permissions for AndroidAuto + private static final ArrayList PERMISSIONS_ANDROIDAUTO = new ArrayList( + Arrays.asList( + "android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY", + "android.permission.CREATE_VIRTUAL_DEVICE", + "android.permission.INTERNAL_SYSTEM_WINDOW", + "android.permission.MANAGE_COMPANION_DEVICES", + "android.permission.MANAGE_USB", + "android.permission.MODIFY_AUDIO_ROUTING", + "android.permission.READ_PRIVILEGED_PHONE_STATE", + "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION", + "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION", + "android.permission.BLUETOOTH_PRIVILEGED", + "android.permission.LOCAL_MAC_ADDRESS", + "android.permission.REQUEST_COMPANION_SELF_MANAGED", + "android.permission.READ_PHONE_STATE" + ) + ); + + /* Define additionally allowed permissions for Screen2Auto - these will only be allowed when car is connected(!) */ + private static final ArrayList PERMISSIONS_SCREEN2AUTO = new ArrayList( + Arrays.asList( + "android.permission.CAPTURE_VIDEO_OUTPUT", // avoid cast confirmation dialog + "android.permission.SYSTEM_APPLICATION_OVERLAY", // display over other apps + "android.permission.START_ACTIVITIES_FROM_BACKGROUND" + ) + ); + // grant additional permissions while screen2auto is capturing the screen + private static final ArrayList PERMISSIONS_SCREEN2AUTO_DURING_SCREENCAPTURE = new ArrayList( + Arrays.asList( + "android.permission.BIND_ACCESSIBILITY_SERVICE" + ) + ); + + // Spoof permission checks for Screen2Auto + private static final ArrayList SPOOF_PERMISSIONS_SCREEN2AUTO = new ArrayList( + Arrays.asList( + "android.permission.SYSTEM_APPLICATION_OVERLAY" // display over other apps + ) + ); + + private static boolean isAndroidAuto = false; + private static boolean isScreen2Auto = false; + private static boolean isMediaApp = false; + private static Context context; + + // Static only + private AndroidAutoHelper() { } + + /** @hide */ + public static Context appContext() { + return context; + } + + private static boolean uidBelongsToOneOfPackages(int uid, List packages) { + if (uid == 0) { + return false; + } + try { + return packages.stream().anyMatch( + e -> Arrays.asList(context.getPackageManager().getPackagesForUid(uid)).contains(e) + ); + } catch (Exception ignored) {} + return false; + } + + private static boolean uidBelongsToPackage(int uid, String packageName) { + return uidBelongsToOneOfPackages(uid, Collections.singletonList(packageName)); + } + + /** @hide */ + public static boolean isAndroidAutoContext() { + return isAndroidAuto; + } + + private static boolean validateCertDigests(Signature[] signatures, Set validSignatureDigests) throws NoSuchAlgorithmException { + for (Signature signature : signatures) { + String signatureDigest = PackageUtils.computeSha256Digest(signature.toByteArray()); + + if (validSignatureDigests.contains(signatureDigest)) { + return true; + } + } + return false; + } + + private static boolean packageMatchesSignatureDigests(String packageName, Set validSignatureDigests) { + IPackageManager pm = ActivityThread.getPackageManager(); + try { + PackageInfo pkg = pm.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES, 0); + SigningInfo si = pkg.signingInfo; + Signature[] signatures = si.getApkContentsSigners(); + + boolean validCert = validateCertDigests(signatures, validSignatureDigests); + + if (!validCert && si.hasPastSigningCertificates()) { + Signature[] pastSignatures = si.getSigningCertificateHistory(); + validCert = validateCertDigests(pastSignatures, validSignatureDigests); + } + + return validCert; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } catch (NoSuchAlgorithmException ignore) {} // won't happen + + return false; + } + + /** + * Checks if packageName is AndroidAuto and package has matching signature + * + * @hide + */ + public static boolean isAndroidAuto(String packageName) { + if (PACKAGE_ANDROIDAUTO.equals(packageName) + && packageMatchesSignatureDigests(packageName, SIGNATURES_ANDROIDAUTO)) { + return true; + } + return false; + } + + /** + * Checks if uid belongs to AndroidAuto, and package has matching signature + * + * @hide + */ + public static boolean isAndroidAuto(int uid) { + return uidBelongsToPackage(uid, PACKAGE_ANDROIDAUTO) && isAndroidAuto(PACKAGE_ANDROIDAUTO); + } + + /** + * Checks if packageName and uid belong to AndroidAuto, and package has matching signature + * + * @hide + */ + public static boolean isAndroidAuto(String packageName, int uid) { + if (PACKAGE_ANDROIDAUTO.equals(packageName) && isAndroidAuto(uid)) { + return true; + } + return false; + } + + /** + * Checks if packageName is AndroidAuto and signingDetails match + * + * @hide + */ + public static boolean isAndroidAuto(String packageName, SigningDetails signingDetails) { + if (PACKAGE_ANDROIDAUTO.equals(packageName) + && signingDetails.hasAncestorOrSelfWithDigest(SIGNATURES_ANDROIDAUTO)) { + return true; + } + return false; + } + + /** + * Checks if packageName is Screen2Auto and package has matching signature + * + * @hide + */ + public static boolean isScreen2Auto(String packageName) { + if (PACKAGE_SCREEN2AUTO.equals(packageName) + && packageMatchesSignatureDigests(packageName, SIGNATURES_SCREEN2AUTO)) { + return true; + } + return false; + } + + /** @hide */ + public static boolean isScreen2AutoContext() { return isScreen2Auto; } + + /** + * Checks if uid belongs to Screen2Auto, and package has matching signature + * + * @hide + */ + public static boolean isScreen2Auto(int uid) { + return uidBelongsToPackage(uid, PACKAGE_SCREEN2AUTO) && isScreen2Auto(PACKAGE_SCREEN2AUTO); + } + + /** + * Checks if packageName is Screen2Auto and signingDetails match + * + * @hide + */ + public static boolean isScreen2Auto(String packageName, SigningDetails signingDetails) { + if (PACKAGE_SCREEN2AUTO.equals(packageName) + && signingDetails.hasAncestorOrSelfWithDigest(SIGNATURES_SCREEN2AUTO)) { + return true; + } + return false; + } + + /** + * Checks if additional permission should be granted + * + * @hide + */ + public static boolean hasAdditionalPermission(String packageName, String permissionName, SigningDetails signingDetails) { + + if (PACKAGE_ANDROIDAUTO.equals(packageName) && isAndroidAuto(packageName, signingDetails) + && PERMISSIONS_ANDROIDAUTO.contains(permissionName)) { + return true; + } + + if (PACKAGE_SCREEN2AUTO.equals(packageName) && androidAutoActive && isScreen2Auto(packageName, signingDetails)) { + if (PERMISSIONS_SCREEN2AUTO.contains(permissionName)) { + return true; + } + if (screenCaptureActive && PERMISSIONS_SCREEN2AUTO_DURING_SCREENCAPTURE.contains(permissionName)) { + return true; + } + } + + return false; + } + + /** @hide */ + public static boolean isMediaAppContext() { + return isMediaApp; + } + + /** @hide */ + public static boolean isMediaApp(int uid) { + return uidBelongsToOneOfPackages(uid, PACKAGES_MEDIAAPPS); + } + + /** @hide */ + public static void applicationStart(Context context) { + AndroidAutoHelper.context = context; + ApplicationInfo appInfo = context.getApplicationInfo(); + + if (appInfo == null || !appInfo.enabled) { + return; + } + + String pkgName = appInfo.packageName; + + isAndroidAuto = isAndroidAuto(pkgName); // also checks signature + isScreen2Auto = isScreen2Auto(pkgName); // also checks signature + isMediaApp = PACKAGES_MEDIAAPPS.contains(pkgName); + } + + private static void handleDisplayChanged(String name, int ownerUid, boolean added) + { + if (name.equals("Dashboard") && isAndroidAuto(ownerUid)) { + androidAutoActive = added; + } + if (name.equals("ScreenCapture") && isScreen2Auto(ownerUid)) { + setScreenCaptureActive(added); + } + } + + /** @hide */ + public static void handleDisplayAdded(String name, int ownerUid) { + handleDisplayChanged(name, ownerUid, true); + } + + /** @hide */ + public static void handleDisplayRemoved(String name, int ownerUid) { + handleDisplayChanged(name, ownerUid, false); + } + + /** + * adds/removes Screen2Auto's accessibility service when "ScreenCapture" display device is added/removed. + * */ + private static void setScreenCaptureActive(boolean screenCaptureActiveStatus) { + screenCaptureActive = screenCaptureActiveStatus; + + String accessibilityService = PACKAGE_SCREEN2AUTO + "/ru.inceptive.screentwoauto.services.SplitScreenService"; + + int accessibilityEnabled = 0; + + try { + accessibilityEnabled = Settings.Secure.getInt( + context.getContentResolver(), + android.provider.Settings.Secure.ACCESSIBILITY_ENABLED); + + if (accessibilityEnabled == 0) { + Settings.Secure.putInt(context.getContentResolver(), + android.provider.Settings.Secure.ACCESSIBILITY_ENABLED, 1); + } + + String services = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); + if (screenCaptureActiveStatus && ((services == null) || !services.contains(accessibilityService))) { + if (services == null) { + services = ""; + } + if (services.length() > 0) { + services += ":"; + } + services += accessibilityService; + } else if (!screenCaptureActiveStatus && (services != null) && services.contains(accessibilityService)) { + services = services.replace(accessibilityService, ""); + } + + services = services.replace("::", ":"); + if (services.length() <= 1) { + services = null; + } + + Settings.Secure.putString(context.getContentResolver(), + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, services); + } catch (Exception e) { + Log.e("AAH", "S2A accessibility service exception", e); + } + } + + /** @hide */ + public static boolean isScreenCaptureActive() { + return screenCaptureActive; + } + + /** @hide */ + public static boolean shouldSpoofSelfPermissionCheck(String perm) { + return isScreen2Auto && SPOOF_PERMISSIONS_SCREEN2AUTO.contains(perm); + } +} diff -wurN a/frameworks/base/core/java/android/app/ContextImpl.java b/frameworks/base/core/java/android/app/ContextImpl.java --- a/frameworks/base/core/java/android/app/ContextImpl.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/core/java/android/app/ContextImpl.java 2023-08-30 10:14:29.559387205 +0200 @@ -27,6 +27,7 @@ import android.annotation.Nullable; import android.annotation.UiContext; import android.app.compat.gms.GmsCompat; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.AutofillOptions; @@ -2264,6 +2265,10 @@ } } + if (AndroidAutoHelper.shouldSpoofSelfPermissionCheck(permission)) { + return PERMISSION_GRANTED; + } + return checkPermission(permission, Process.myPid(), Process.myUid()); } diff -wurN a/frameworks/base/core/java/android/app/Instrumentation.java b/frameworks/base/core/java/android/app/Instrumentation.java --- a/frameworks/base/core/java/android/app/Instrumentation.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/core/java/android/app/Instrumentation.java 2023-08-28 15:25:13.929933006 +0200 @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.compat.gms.GmsCompat; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.UnsupportedAppUsage; import android.content.ActivityNotFoundException; import android.content.ComponentName; @@ -58,6 +59,7 @@ import com.android.internal.app.StorageScopesAppHooks; import com.android.internal.content.ReferrerIntent; + import com.android.internal.gmscompat.GmsHooks; import java.io.File; @@ -1243,6 +1245,7 @@ throws InstantiationException, IllegalAccessException, ClassNotFoundException { GmsCompat.maybeEnable(context); + AndroidAutoHelper.applicationStart(context); Application app = getFactory(context.getPackageName()) .instantiateApplication(cl, className); app.attach(context); @@ -1262,6 +1265,7 @@ throws InstantiationException, IllegalAccessException, ClassNotFoundException { GmsCompat.maybeEnable(context); + AndroidAutoHelper.applicationStart(context); Application app = (Application)clazz.newInstance(); app.attach(context); return app; diff -wurN a/frameworks/base/core/java/android/view/SurfaceView.java b/frameworks/base/core/java/android/view/SurfaceView.java --- a/frameworks/base/core/java/android/view/SurfaceView.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/core/java/android/view/SurfaceView.java 2023-08-28 15:25:13.929933006 +0200 @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.CompatibilityInfo.Translator; @@ -688,7 +689,7 @@ * @param isSecure True if the surface view is secure. */ public void setSecure(boolean isSecure) { - if (isSecure) { + if (isSecure && !AndroidAutoHelper.isMediaAppContext()) { mSurfaceFlags |= SurfaceControl.SECURE; } else { mSurfaceFlags &= ~SurfaceControl.SECURE; diff -wurN a/frameworks/base/core/java/android/view/Window.java b/frameworks/base/core/java/android/view/Window.java --- a/frameworks/base/core/java/android/view/Window.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/core/java/android/view/Window.java 2023-08-28 15:25:13.929933006 +0200 @@ -34,6 +34,7 @@ import android.annotation.TestApi; import android.annotation.UiContext; import android.app.WindowConfiguration; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ActivityInfo; @@ -1280,6 +1281,9 @@ */ public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes(); + if (AndroidAutoHelper.isMediaAppContext()) { + flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + } attrs.flags = (attrs.flags&~mask) | (flags&mask); mForcedWindowFlags |= mask; dispatchWindowAttributesChanged(attrs); diff -wurN a/frameworks/base/core/java/android/view/WindowManagerGlobal.java b/frameworks/base/core/java/android/view/WindowManagerGlobal.java --- a/frameworks/base/core/java/android/view/WindowManagerGlobal.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/core/java/android/view/WindowManagerGlobal.java 2023-08-28 15:25:13.929933006 +0200 @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentCallbacks2; import android.content.Context; @@ -318,6 +319,10 @@ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } + if (AndroidAutoHelper.isMediaAppContext()) { + ((WindowManager.LayoutParams) params).flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + } + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); @@ -422,6 +427,10 @@ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } + if (AndroidAutoHelper.isMediaAppContext()) { + ((WindowManager.LayoutParams) params).flags &= ~WindowManager.LayoutParams.FLAG_SECURE; + } + final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; view.setLayoutParams(wparams); diff -wurN a/frameworks/base/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/frameworks/base/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java --- a/frameworks/base/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java 2023-08-28 15:25:13.929933006 +0200 @@ -19,6 +19,7 @@ import static android.app.PendingIntent.FLAG_CANCEL_CURRENT; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; +import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; import static android.companion.CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME; import static android.content.ComponentName.createRelative; @@ -34,6 +35,7 @@ import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.app.PendingIntent; +import android.app.compat.sn00x.AndroidAutoHelper; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.IAssociationRequestCallback; @@ -175,6 +177,17 @@ createAssociationAndNotifyApplication(request, packageName, userId, /*macAddress*/ null, callback); return; + } + + // create association for AndroidAuto right away + // alternatively packageName (including cert digest) could be added to config_systemAutomotiveProjection + // to grant the role android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION. However, though it would make willAddRoleHolder() pass, + // more invasive permissions (e.g. microphone) would be granted. + if (DEVICE_PROFILE_AUTOMOTIVE_PROJECTION.equals(request.getDeviceProfile()) + && AndroidAutoHelper.isAndroidAuto(packageName, packageUid)) { + createAssociationAndNotifyApplication(request, packageName, userId, + /*macAddress*/ null, callback); + return; } // 2b. Build a PendingIntent for launching the confirmation UI, and send it back to the app: diff -wurN a/frameworks/base/services/companion/java/com/android/server/companion/PermissionsUtils.java b/frameworks/base/services/companion/java/com/android/server/companion/PermissionsUtils.java --- a/frameworks/base/services/companion/java/com/android/server/companion/PermissionsUtils.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/services/companion/java/com/android/server/companion/PermissionsUtils.java 2023-08-28 15:25:13.929933006 +0200 @@ -36,6 +36,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.compat.sn00x.AndroidAutoHelper; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; @@ -166,6 +167,9 @@ @Nullable String actionDescription) { if (checkCallerCanManageAssociationsForPackage(context, userId, packageName)) return; + // Allow AndroidAuto to manage it's associations + if (userId == 0 && AndroidAutoHelper.isAndroidAuto(packageName, getCallingUid())) return; + throw new SecurityException("Caller (uid=" + getCallingUid() + ") does not have " + "permissions to " + (actionDescription != null ? actionDescription : "manage associations") diff -wurN a/frameworks/base/services/core/java/com/android/server/display/DisplayDeviceRepository.java b/frameworks/base/services/core/java/com/android/server/display/DisplayDeviceRepository.java --- a/frameworks/base/services/core/java/com/android/server/display/DisplayDeviceRepository.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/services/core/java/com/android/server/display/DisplayDeviceRepository.java 2023-08-29 16:10:13.101421332 +0200 @@ -17,6 +17,7 @@ package com.android.server.display; import android.annotation.NonNull; +import android.app.compat.sn00x.AndroidAutoHelper; import android.os.Trace; import android.util.Slog; import android.view.Display; @@ -156,6 +157,7 @@ mDisplayDevices.add(device); sendEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED); + AndroidAutoHelper.handleDisplayAdded(info.name, info.ownerUid); } } @@ -205,6 +207,7 @@ Slog.i(TAG, "Display device removed: " + info); device.mDebugLastLoggedDeviceInfo = info; sendEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); + AndroidAutoHelper.handleDisplayRemoved(info.name, info.ownerUid); } } diff -wurN a/frameworks/base/services/core/java/com/android/server/pm/ComputerEngine.java b/frameworks/base/services/core/java/com/android/server/pm/ComputerEngine.java --- a/frameworks/base/services/core/java/com/android/server/pm/ComputerEngine.java 2023-08-30 14:57:19.378620736 +0200 +++ b/frameworks/base/services/core/java/com/android/server/pm/ComputerEngine.java 2023-08-28 15:25:13.929933006 +0200 @@ -65,6 +65,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.compat.sn00x.AndroidAutoHelper; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -169,6 +170,8 @@ import java.util.Set; import java.util.UUID; +import static com.android.internal.gmscompat.GmsInfo.PACKAGE_PLAY_STORE; + /** * This class contains the implementation of the Computer functions. It * is entirely self-contained - it has no implicit access to @@ -5103,6 +5106,10 @@ final int callingUid = Binder.getCallingUid(); final int userId = UserHandle.getUserId(callingUid); + if (AndroidAutoHelper.isAndroidAuto(callingUid)) { + return new InstallSourceInfo(PACKAGE_PLAY_STORE, null, PACKAGE_PLAY_STORE, PACKAGE_PLAY_STORE); + } + String installerPackageName; String initiatingPackageName; String originatingPackageName; diff -wurN a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java --- a/frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java 2023-08-30 14:57:19.390620702 +0200 +++ b/frameworks/base/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java 2023-08-28 15:25:13.933933009 +0200 @@ -16,6 +16,7 @@ package com.android.server.pm; +import static android.content.Intent.ACTION_MAIN; import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE; import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; @@ -37,6 +38,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.content.Context; @@ -1097,6 +1099,11 @@ Intent intent, String resolvedType, int filterCallingUid) { if (DISABLE_ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS.get()) return; + // Allow screen2auto to start apps targeting Android 13 + if (ACTION_MAIN.equals(intent.getAction()) && AndroidAutoHelper.isScreen2Auto(filterCallingUid)) { + return; + } + final Printer logPrinter = DEBUG_INTENT_MATCHING ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM) : null; diff -wurN a/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java --- a/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java 2023-08-30 14:57:19.390620702 +0200 +++ b/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java 2023-08-30 14:52:40.723680369 +0200 @@ -67,6 +67,7 @@ import android.app.ActivityManager; import android.app.IActivityManager; import android.app.admin.DevicePolicyManagerInternal; +import android.app.compat.sn00x.AndroidAutoHelper; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.content.Context; @@ -178,7 +179,6 @@ private static final String SKIP_KILL_APP_REASON_NOTIFICATION_TEST = "skip permission revoke " + "app kill for notification test"; - private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60); /** Cap the size of permission trees that 3rd party apps can define; in characters of text */ @@ -965,6 +965,10 @@ return PackageManager.PERMISSION_DENIED; } + if (AndroidAutoHelper.hasAdditionalPermission(pkg.getPackageName(), permissionName, pkg.getSigningDetails())) { + return PackageManager.PERMISSION_GRANTED; + } + if (checkSinglePermissionInternalLocked(uidState, permissionName, isInstantApp)) { return PackageManager.PERMISSION_GRANTED; } diff -wurN a/frameworks/base/services/core/java/com/android/server/wm/WindowState.java b/frameworks/base/services/core/java/com/android/server/wm/WindowState.java --- a/frameworks/base/services/core/java/com/android/server/wm/WindowState.java 2023-08-30 14:57:19.390620702 +0200 +++ b/frameworks/base/services/core/java/com/android/server/wm/WindowState.java 2023-08-28 15:25:13.933933009 +0200 @@ -193,6 +193,7 @@ import android.app.ActivityTaskManager; import android.app.AppOpsManager; import android.app.admin.DevicePolicyCache; +import android.app.compat.sn00x.AndroidAutoHelper; import android.content.Context; import android.content.res.Configuration; import android.graphics.Matrix; @@ -2020,7 +2021,7 @@ } boolean isSecureLocked() { - if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { + if (!AndroidAutoHelper.isMediaApp(mShowUserId) && (mAttrs.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0) { return true; } return !DevicePolicyCache.getInstance().isScreenCaptureAllowed(mShowUserId);