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

Commit 5d39efec authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Create DEVICE_PROFILE_AUTOMOTIVE_PROJECTION"

parents f3abfbca f674c23d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ package android {
    field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final String RENOUNCE_PERMISSIONS = "android.permission.RENOUNCE_PERMISSIONS";
    field public static final String REQUEST_COMPANION_PROFILE_APP_STREAMING = "android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING";
    field public static final String REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION = "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION";
    field public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
    field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
    field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
@@ -2342,6 +2343,7 @@ package android.companion {
  public final class AssociationRequest implements android.os.Parcelable {
    field @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING) public static final String DEVICE_PROFILE_APP_STREAMING = "android.app.role.COMPANION_DEVICE_APP_STREAMING";
    field @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION) public static final String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION = "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION";
  }
  public final class CompanionDeviceManager {
+17 −2
Original line number Diff line number Diff line
@@ -94,6 +94,21 @@ public final class AssociationRequest implements Parcelable {
    public static final String DEVICE_PROFILE_APP_STREAMING =
            "android.app.role.COMPANION_DEVICE_APP_STREAMING";

    /**
     * Device profile: Android Automotive Projection
     *
     * Only applications that have been granted
     * {@link android.Manifest.permission#REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION} are
     * allowed to request to be associated with such devices.
     *
     * @see AssociationRequest.Builder#setDeviceProfile
     * @hide
     */
    @RequiresPermission(Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION)
    @SystemApi
    public static final String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION =
            "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION";

    /** @hide */
    @StringDef(value = { DEVICE_PROFILE_WATCH })
    public @interface DeviceProfile {}
@@ -498,10 +513,10 @@ public final class AssociationRequest implements Parcelable {
    };

    @DataClass.Generated(
            time = 1634716126923L,
            time = 1635190605212L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/core/java/android/companion/AssociationRequest.java",
            inputSignatures = "private static final  java.lang.String LOG_TAG\npublic static final  java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_APP_STREAMING\nprivate  boolean mSingleDevice\nprivate @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.String mCallingPackage\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate  long mCreationTime\nprivate  boolean mSkipPrompt\nprivate  void onConstructed()\npublic  void setCallingPackage(java.lang.String)\npublic  void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic  void setSkipPrompt(boolean)\npublic @android.compat.annotation.UnsupportedAppUsage boolean isSingleDevice()\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genHiddenConstructor=true, genBuilder=false, genConstDefs=false)")
            inputSignatures = "private static final  java.lang.String LOG_TAG\npublic static final  java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_APP_STREAMING\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION\nprivate  boolean mSingleDevice\nprivate @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.String mCallingPackage\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate  long mCreationTime\nprivate  boolean mSkipPrompt\nprivate  void onConstructed()\npublic  void setCallingPackage(java.lang.String)\npublic  void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic  void setSkipPrompt(boolean)\npublic @android.compat.annotation.UnsupportedAppUsage boolean isSingleDevice()\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genHiddenConstructor=true, genBuilder=false, genConstDefs=false)")
    @Deprecated
    private void __metadata() {}

+11 −0
Original line number Diff line number Diff line
@@ -2990,6 +2990,17 @@
    <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING"
                android:protectionLevel="signature|privileged" />

    <!-- Allows application to request to be associated with a vehicle head unit capable of
         automotive projection
         ({@link android.companion.AssociationRequest#DEVICE_PROFILE_AUTOMOTIVE_PROJECTION})
         by {@link android.companion.CompanionDeviceManager}.
        <p>Not for use by third-party applications.
         @hide
         @SystemApi
    -->
    <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION"
                android:protectionLevel="internal|role" />

    <!-- Allows a companion app to associate to Wi-Fi.
         <p>Only for use by a single pre-approved app.
         @hide
+32 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.companion;

import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION;
import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

@@ -32,6 +33,7 @@ import static java.util.Collections.unmodifiableMap;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.role.RoleManager;
import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
@@ -41,8 +43,10 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.Signature;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.PackageUtils;
import android.util.Slog;
@@ -56,6 +60,7 @@ import com.android.server.FgThread;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -69,6 +74,8 @@ class AssociationRequestsProcessor {
        map.put(DEVICE_PROFILE_WATCH, Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);
        map.put(DEVICE_PROFILE_APP_STREAMING,
                Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING);
        map.put(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION,
                Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION);

        DEVICE_PROFILE_TO_PERMISSION = unmodifiableMap(map);
    }
@@ -87,12 +94,14 @@ class AssociationRequestsProcessor {
    private IFindDeviceCallback mFindDeviceCallback;
    private String mCallingPackage;
    private AndroidFuture<?> mOngoingDeviceDiscovery;
    private RoleManager mRoleManager;

    private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;

    AssociationRequestsProcessor(CompanionDeviceManagerService service) {
    AssociationRequestsProcessor(CompanionDeviceManagerService service, RoleManager roleManager) {
        mContext = service.getContext();
        mService = service;
        mRoleManager = roleManager;

        final Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
        mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
@@ -165,6 +174,16 @@ class AssociationRequestsProcessor {
                }));
    }

    private boolean isRoleHolder(int userId, String packageName, String role) {
        final long identity = Binder.clearCallingIdentity();
        try {
            List<String> holders = mRoleManager.getRoleHoldersAsUser(role, UserHandle.of(userId));
            return holders.contains(packageName);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    void stopScan(AssociationRequest request, IFindDeviceCallback callback, String callingPackage) {
        if (DEBUG) {
            Slog.d(TAG, "stopScan(request = " + request + ")");
@@ -186,6 +205,12 @@ class AssociationRequestsProcessor {
                    "DEVICE_PROFILE_APP_STREAMING is not fully supported yet.");
        }

        if (DEVICE_PROFILE_AUTOMOTIVE_PROJECTION.equals(deviceProfile)) {
            // TODO: remove, when properly supporting this profile.
            throw new UnsupportedOperationException(
                    "DEVICE_PROFILE_AUTOMOTIVE_PROJECTION is not fully supported yet.");
        }

        if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
            throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
        }
@@ -217,6 +242,12 @@ class AssociationRequestsProcessor {
    }

    private boolean mayAssociateWithoutPrompt(String packageName, int userId) {
        if (mRequest.getDeviceProfile() != null
                && isRoleHolder(userId, packageName, mRequest.getDeviceProfile())) {
            // Don't need to collect user's consent since app already holds the role.
            return true;
        }

        String[] sameOemPackages = mContext.getResources()
                .getStringArray(com.android.internal.R.array.config_companionDevicePackages);
        if (!ArrayUtils.contains(sameOemPackages, packageName)) {
+1 −1
Original line number Diff line number Diff line
@@ -200,7 +200,6 @@ public class CompanionDeviceManagerService extends SystemService {
        super(context);
        mImpl = new CompanionDeviceManagerImpl();
        mPersistentDataStore = new PersistentDataStore();
        mAssociationRequestsProcessor = new AssociationRequestsProcessor(this);

        mPowerWhitelistManager = context.getSystemService(PowerWhitelistManager.class);
        mRoleManager = context.getSystemService(RoleManager.class);
@@ -213,6 +212,7 @@ public class CompanionDeviceManagerService extends SystemService {
                context.getSystemService(PermissionControllerManager.class));
        mUserManager = context.getSystemService(UserManager.class);
        mCompanionDevicePresenceController = new CompanionDevicePresenceController();
        mAssociationRequestsProcessor = new AssociationRequestsProcessor(this, mRoleManager);

        registerPackageMonitor();
    }