Merge "Replace CDM profiles hardcoded strings with real values"

This commit is contained in:
TreeHugger Robot
2021-01-13 00:32:04 +00:00
committed by Android (Google) Code Review
6 changed files with 148 additions and 31 deletions

View File

@@ -96,11 +96,25 @@ public final class AssociationRequest implements Parcelable {
*/
private @Nullable String mCallingPackage = null;
/**
* The user-readable description of the device profile's privileges.
*
* Populated by the system.
*
* @hide
*/
private @Nullable String mDeviceProfilePrivilegesDescription = null;
/** @hide */
public void setCallingPackage(@NonNull String pkg) {
mCallingPackage = pkg;
}
/** @hide */
public void setDeviceProfilePrivilegesDescription(@NonNull String desc) {
mDeviceProfilePrivilegesDescription = desc;
}
private void onConstructed() {
if (mDeviceProfile != null
&& !Objects.equals(mDeviceProfile, DEVICE_PROFILE_WATCH)) {
@@ -178,14 +192,14 @@ public final class AssociationRequest implements Parcelable {
markUsed();
return new AssociationRequest(
mSingleDevice, emptyIfNull(mDeviceFilters),
mDeviceProfile, null);
mDeviceProfile, null, null);
}
}
// Code below generated by codegen v1.0.20.
// Code below generated by codegen v1.0.22.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -215,6 +229,10 @@ public final class AssociationRequest implements Parcelable {
* The app package making the request.
*
* Populated by the system.
* @param deviceProfilePrivilegesDescription
* The user-readable description of the device profile's privileges.
*
* Populated by the system.
* @hide
*/
@DataClass.Generated.Member
@@ -222,7 +240,8 @@ public final class AssociationRequest implements Parcelable {
boolean singleDevice,
@NonNull List<DeviceFilter<?>> deviceFilters,
@Nullable @DeviceProfile String deviceProfile,
@Nullable String callingPackage) {
@Nullable String callingPackage,
@Nullable String deviceProfilePrivilegesDescription) {
this.mSingleDevice = singleDevice;
this.mDeviceFilters = deviceFilters;
com.android.internal.util.AnnotationValidations.validate(
@@ -231,6 +250,7 @@ public final class AssociationRequest implements Parcelable {
com.android.internal.util.AnnotationValidations.validate(
DeviceProfile.class, null, mDeviceProfile);
this.mCallingPackage = callingPackage;
this.mDeviceProfilePrivilegesDescription = deviceProfilePrivilegesDescription;
onConstructed();
}
@@ -257,6 +277,18 @@ public final class AssociationRequest implements Parcelable {
return mCallingPackage;
}
/**
* The user-readable description of the device profile's privileges.
*
* Populated by the system.
*
* @hide
*/
@DataClass.Generated.Member
public @Nullable String getDeviceProfilePrivilegesDescription() {
return mDeviceProfilePrivilegesDescription;
}
@Override
@DataClass.Generated.Member
public String toString() {
@@ -267,7 +299,8 @@ public final class AssociationRequest implements Parcelable {
"singleDevice = " + mSingleDevice + ", " +
"deviceFilters = " + mDeviceFilters + ", " +
"deviceProfile = " + mDeviceProfile + ", " +
"callingPackage = " + mCallingPackage +
"callingPackage = " + mCallingPackage + ", " +
"deviceProfilePrivilegesDescription = " + mDeviceProfilePrivilegesDescription +
" }";
}
@@ -287,7 +320,8 @@ public final class AssociationRequest implements Parcelable {
&& mSingleDevice == that.mSingleDevice
&& Objects.equals(mDeviceFilters, that.mDeviceFilters)
&& Objects.equals(mDeviceProfile, that.mDeviceProfile)
&& Objects.equals(mCallingPackage, that.mCallingPackage);
&& Objects.equals(mCallingPackage, that.mCallingPackage)
&& Objects.equals(mDeviceProfilePrivilegesDescription, that.mDeviceProfilePrivilegesDescription);
}
@Override
@@ -301,6 +335,7 @@ public final class AssociationRequest implements Parcelable {
_hash = 31 * _hash + Objects.hashCode(mDeviceFilters);
_hash = 31 * _hash + Objects.hashCode(mDeviceProfile);
_hash = 31 * _hash + Objects.hashCode(mCallingPackage);
_hash = 31 * _hash + Objects.hashCode(mDeviceProfilePrivilegesDescription);
return _hash;
}
@@ -314,10 +349,12 @@ public final class AssociationRequest implements Parcelable {
if (mSingleDevice) flg |= 0x1;
if (mDeviceProfile != null) flg |= 0x4;
if (mCallingPackage != null) flg |= 0x8;
if (mDeviceProfilePrivilegesDescription != null) flg |= 0x10;
dest.writeByte(flg);
dest.writeParcelableList(mDeviceFilters, flags);
if (mDeviceProfile != null) dest.writeString(mDeviceProfile);
if (mCallingPackage != null) dest.writeString(mCallingPackage);
if (mDeviceProfilePrivilegesDescription != null) dest.writeString(mDeviceProfilePrivilegesDescription);
}
@Override
@@ -337,6 +374,7 @@ public final class AssociationRequest implements Parcelable {
in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader());
String deviceProfile = (flg & 0x4) == 0 ? null : in.readString();
String callingPackage = (flg & 0x8) == 0 ? null : in.readString();
String deviceProfilePrivilegesDescription = (flg & 0x10) == 0 ? null : in.readString();
this.mSingleDevice = singleDevice;
this.mDeviceFilters = deviceFilters;
@@ -346,6 +384,7 @@ public final class AssociationRequest implements Parcelable {
com.android.internal.util.AnnotationValidations.validate(
DeviceProfile.class, null, mDeviceProfile);
this.mCallingPackage = callingPackage;
this.mDeviceProfilePrivilegesDescription = deviceProfilePrivilegesDescription;
onConstructed();
}
@@ -365,10 +404,10 @@ public final class AssociationRequest implements Parcelable {
};
@DataClass.Generated(
time = 1604534468409L,
codegenVersion = "1.0.20",
time = 1610132130920L,
codegenVersion = "1.0.22",
sourceFile = "frameworks/base/core/java/android/companion/AssociationRequest.java",
inputSignatures = "public static final java.lang.String DEVICE_PROFILE_WATCH\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\npublic void setCallingPackage(java.lang.String)\nprivate void onConstructed()\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)")
inputSignatures = "public static final java.lang.String DEVICE_PROFILE_WATCH\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\npublic void setCallingPackage(java.lang.String)\npublic void setDeviceProfilePrivilegesDescription(java.lang.String)\nprivate void onConstructed()\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)")
@Deprecated
private void __metadata() {}

View File

@@ -662,6 +662,34 @@ public final class PermissionControllerManager {
}, executor);
}
/**
* Gets the description of the privileges associated with the given device profiles
*
* @param profileName Name of the device profile
* @param executor Executor on which to invoke the callback
* @param callback Callback to receive the result
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_COMPANION_DEVICES)
public void getPrivilegesDescriptionStringForProfile(
@NonNull String profileName,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<String> callback) {
mRemoteService.postAsync(service -> {
AndroidFuture<String> future = new AndroidFuture<>();
service.getPrivilegesDescriptionStringForProfile(profileName, future);
return future;
}).whenCompleteAsync((description, err) -> {
if (err != null) {
Log.e(TAG, "Error from getPrivilegesDescriptionStringForProfile", err);
callback.accept(null);
} else {
callback.accept(description);
}
}, executor);
}
/**
* @see PermissionControllerManager#updateUserSensitiveForApp
* @hide

View File

@@ -540,12 +540,13 @@ public abstract class PermissionControllerService extends Service {
public void getPrivilegesDescriptionStringForProfile(
@NonNull String deviceProfileName,
@NonNull AndroidFuture<String> callback) {
checkStringNotEmpty(deviceProfileName);
Objects.requireNonNull(callback);
enforceSomePermissionsGrantedToCaller(Manifest.permission.MANAGE_COMPANION_DEVICES);
try {
checkStringNotEmpty(deviceProfileName);
Objects.requireNonNull(callback);
enforceSomePermissionsGrantedToCaller(
Manifest.permission.MANAGE_COMPANION_DEVICES);
callback.complete(PermissionControllerService
.this
.getPrivilegesDescriptionStringForProfile(deviceProfileName));

View File

@@ -25,11 +25,14 @@
<!-- The generic placeholder for a device type when nothing specific is known about it [CHAR LIMIT=30] -->
<string name="profile_name_generic">device</string>
<!-- The name of the "watch" device type [CHAR LIMIT=30] -->
<string name="profile_name_watch">watch</string>
<!-- Title of the device association confirmation dialog. -->
<string name="confirmation_title">Set &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to manage your <xliff:g id="profile_name" example="watch">%2$s</xliff:g> - &lt;strong&gt;<xliff:g id="device_name" example="ASUS ZenWatch 2">%3$s</xliff:g>&lt;/strong&gt;</string>
<!-- Text of the device profile permissions explanation in the association dialog. -->
<string name="profile_summary"><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g> is needed to manage your <xliff:g id="profile_name" example="watch">%2$s</xliff:g>. <xliff:g id="app_name2" example="Android Wear">%3$s</xliff:g> will get access to <xliff:g id="permissions" example="Notifications, Calendar and Phone">%4$s</xliff:g> while the <xliff:g id="profile_name2" example="watch">%5$s</xliff:g> is connected.</string>
<string name="profile_summary"><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g> is needed to manage your <xliff:g id="profile_name" example="watch">%2$s</xliff:g>. <xliff:g id="privileges_discplaimer" example="Android Wear will get access to your Notifications, Calendar and Contacts.">%3$s</xliff:g></string>
<!-- Positive button for the device-app association consent dialog [CHAR LIMIT=30] -->
<string name="consent_yes">Yes</string>

View File

@@ -17,11 +17,13 @@
package com.android.companiondevicemanager;
import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
import static android.text.TextUtils.emptyIfNull;
import static android.text.TextUtils.withoutPrefix;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static java.util.Objects.requireNonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
@@ -65,10 +67,7 @@ public class DeviceChooserActivity extends Activity {
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
String deviceProfile = getRequest().getDeviceProfile();
String profileName = deviceProfile == null
? getString(R.string.profile_name_generic)
//TODO introduce PermissionController APIs to resolve UI values
: withoutPrefix("android.app.role.COMPANION_DEVICE_", deviceProfile).toLowerCase();
String profileName = getDeviceProfileName(deviceProfile);
if (getRequest().isSingleDevice()) {
setContentView(R.layout.device_confirmation);
@@ -112,15 +111,14 @@ public class DeviceChooserActivity extends Activity {
TextView profileSummary = findViewById(R.id.profile_summary);
if (deviceProfile != null) {
//TODO introduce PermissionController APIs to resolve UI values
String privileges = "Notifications, Phone, Contacts and Calendar";
String privacyDisclaimer = emptyIfNull(getRequest()
.getDeviceProfilePrivilegesDescription())
.replace("APP_NAME", getCallingAppName());
profileSummary.setVisibility(View.VISIBLE);
profileSummary.setText(getString(R.string.profile_summary,
getCallingAppName(),
profileName,
getCallingAppName(),
privileges,
profileName));
privacyDisclaimer));
} else {
profileSummary.setVisibility(View.GONE);
}
@@ -135,6 +133,24 @@ public class DeviceChooserActivity extends Activity {
return getService().mRequest;
}
private String getDeviceProfileName(@Nullable String deviceProfile) {
if (deviceProfile == null) {
return getString(R.string.profile_name_generic);
}
switch (deviceProfile) {
case AssociationRequest.DEVICE_PROFILE_WATCH: {
return getString(R.string.profile_name_watch);
}
default: {
Log.wtf(LOG_TAG,
"No localized profile name found for device profile: " + deviceProfile);
return withoutPrefix("android.app.role.COMPANION_DEVICE_", deviceProfile)
.toLowerCase()
.replace('_', ' ');
}
}
}
private void cancel() {
getService().onCancel();
setResult(RESULT_CANCELED);

View File

@@ -27,6 +27,7 @@ import static com.android.internal.util.Preconditions.checkState;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MINUTES;
import android.annotation.CheckResult;
@@ -72,6 +73,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.UserHandle;
import android.os.UserManager;
import android.permission.PermissionControllerManager;
import android.provider.Settings;
import android.provider.SettingsStringUtil.ComponentNameSet;
import android.text.BidiFormatter;
@@ -159,6 +161,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
private AssociationRequest mRequest;
private String mCallingPackage;
private AndroidFuture<Association> mOngoingDeviceDiscovery;
private PermissionControllerManager mPermissionControllerManager;
private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener =
new BluetoothDeviceConnectedListener();
@@ -184,6 +187,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mPermissionControllerManager = requireNonNull(
context.getSystemService(PermissionControllerManager.class));
Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
@@ -344,13 +349,25 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
request.setCallingPackage(callingPackage);
callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
final long callingIdentity = Binder.clearCallingIdentity();
try {
mOngoingDeviceDiscovery = mServiceConnectors.forUser(userId).postAsync(service -> {
AndroidFuture<String> fetchProfileDescription =
request.getDeviceProfile() == null
? AndroidFuture.completedFuture(null)
: getDeviceProfilePermissionDescription(
request.getDeviceProfile());
mOngoingDeviceDiscovery = fetchProfileDescription.thenComposeAsync(description -> {
request.setDeviceProfilePrivilegesDescription(description);
return mServiceConnectors.forUser(userId).postAsync(service -> {
AndroidFuture<Association> future = new AndroidFuture<>();
service.startDiscovery(request, callingPackage, callback, future);
return future;
}).cancelTimeout().whenComplete(uncheckExceptions((association, err) -> {
}).cancelTimeout();
}, FgThread.getExecutor()).whenComplete(uncheckExceptions((association, err) -> {
final long callingIdentity = Binder.clearCallingIdentity();
try {
if (err == null) {
addAssociation(association);
} else {
@@ -358,10 +375,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
callback.onFailure("No devices found: " + err.getMessage());
}
cleanup();
}));
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}));
}
@Override
@@ -904,6 +921,19 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
mCurrentlyConnectedDevices.remove(address);
}
private AndroidFuture<String> getDeviceProfilePermissionDescription(String deviceProfile) {
AndroidFuture<String> result = new AndroidFuture<>();
mPermissionControllerManager.getPrivilegesDescriptionStringForProfile(
deviceProfile, FgThread.getExecutor(), desc -> {
try {
result.complete(requireNonNull(desc));
} catch (Exception e) {
result.completeExceptionally(e);
}
});
return result;
}
private class ShellCmd extends ShellCommand {
public static final String USAGE = "help\n"
+ "list USER_ID\n"