Create DEVICE_PROFILE_AUTOMOTIVE_PROJECTION
Create DEVICE_PROFILE_AUTOMOTIVE_PROJECTION profile and corresponding REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION permission with protection_level: "internal|role" Also add a logic that to skip the prompt if the role is not held by system. Test: make bug: 203459457 Change-Id: I2644f7ed079b0e272f0cc8f4d6e580de49c59064
This commit is contained in:
@@ -244,6 +244,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";
|
||||
@@ -2324,6 +2325,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 {
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>>() {
|
||||
@@ -162,6 +171,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 + ")");
|
||||
@@ -183,6 +202,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);
|
||||
}
|
||||
@@ -214,6 +239,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)) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user