diff options
author | 2023-03-01 20:41:38 +0000 | |
---|---|---|
committer | 2023-05-10 21:05:25 +0000 | |
commit | 5be926fbc4fdc4699d07def32014aa5914a31abb (patch) | |
tree | 7dcbf1701d31b73e9c96d5c0a2c2d7ddfd37a504 | |
parent | c77e0e6ff4e6be7f25033608b12adac1204cb66d (diff) |
Apply bullet permission UI to multiple device dialog
Sepreate to two dialogs for non-null profile.
One for the device chooser and another one for
bullet permission dialog.
Test: Cts
Fix: 271311544, 267646302
Change-Id: I8229ce00f17281736aa91a1a9cceea9aaeee35ee
5 files changed, 89 insertions, 98 deletions
diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml index aae30dfe6223..a0b34690696f 100644 --- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml +++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml @@ -144,7 +144,7 @@ android:visibility="gone" android:duplicateParentState="true" android:clickable="false" - android:text="@string/consent_no" /> + android:text="@string/consent_cancel" /> </LinearLayout> diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index 2502bbf7b40b..539857951ab1 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -28,13 +28,13 @@ <string name="profile_name_watch">watch</string> <!-- Title of the device selection dialog. --> - <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to be managed by <strong><xliff:g id="app_name" example="Android Wear">%2$s</xliff:g></strong></string> + <string name="chooser_title_non_profile">Choose a device to be managed by <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong></string> - <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile (type) [CHAR LIMIT=NONE] --> - <string name="summary_watch">This app is needed to manage your <xliff:g id="device_name" example="My Watch">%1$s</xliff:g>. <xliff:g id="app_name" example="Android Wear">%2$s</xliff:g> will be allowed to sync info, like the name of someone calling, interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions.</string> + <!-- Tile of the multiple devices' dialog. --> + <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to set up</string> - <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile for singleDevice(type) [CHAR LIMIT=NONE] --> - <string name="summary_watch_single_device">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string> + <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile [CHAR LIMIT=NONE] --> + <string name="summary_watch">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string> <!-- ================= DEVICE_PROFILE_GLASSES ================= --> @@ -42,13 +42,10 @@ <string name="confirmation_title_glasses">Allow <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> to manage <strong><xliff:g id="device_name" example="Glasses">%2$s</xliff:g></strong>?</string> <!-- The name of the "glasses" device type [CHAR LIMIT=30] --> - <string name="profile_name_glasses">glasses</string> + <string name="profile_name_glasses">device</string> - <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile (type) [CHAR LIMIT=NONE] --> - <string name="summary_glasses_multi_device">This app is needed to manage <xliff:g id="device_name" example="My Glasses">%1$s</xliff:g>. <xliff:g id="app_name" example="Glasses">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Microphone and Nearby devices permissions.</string> - - <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile for singleDevice(type) [CHAR LIMIT=NONE] --> - <string name="summary_glasses_single_device">This app will be allowed to access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string> + <!-- Description of the privileges the application will get if associated with the companion device of GLASSES profile [CHAR LIMIT=NONE] --> + <string name="summary_glasses">This app will be allowed to access these permissions on your <xliff:g id="device_name" example="phone">%1$s</xliff:g></string> <!-- ================= DEVICE_PROFILE_APP_STREAMING ================= --> @@ -97,9 +94,6 @@ <string name="profile_name_generic">device</string> <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] --> - <string name="summary_generic_single_device">This app will be able to sync info, like the name of someone calling, between your phone and <xliff:g id="device_name" example="My Watch">%1$s</xliff:g></string> - - <!-- Description of the privileges the application will get if associated with the companion device of unspecified profile (type) [CHAR LIMIT=NONE] --> <string name="summary_generic">This app will be able to sync info, like the name of someone calling, between your phone and the chosen device</string> <!-- ================= Buttons ================= --> @@ -110,6 +104,9 @@ <!-- Negative button for the device-app association consent dialog [CHAR LIMIT=30] --> <string name="consent_no">Don\u2019t allow</string> + <!-- Cancel button for the device chooser dialog [CHAR LIMIT=30] --> + <string name="consent_cancel">Cancel</string> + <!-- Back button for the helper consent dialog [CHAR LIMIT=30] --> <string name="consent_back">Back</string> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index e85190be0e1e..222877bbe9e9 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -69,11 +69,13 @@ <style name="PositiveButton" parent="@android:style/Widget.Material.Button.Borderless.Colored"> - <item name="android:layout_width">300dp</item> - <item name="android:layout_height">56dp</item> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">wrap_content</item> <item name="android:layout_marginBottom">2dp</item> <item name="android:textAllCaps">false</item> <item name="android:textSize">14sp</item> + <item name="android:layout_marginStart">32dp</item> + <item name="android:layout_marginEnd">32dp</item> <item name="android:textColor">@android:color/system_neutral1_900</item> <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item> <item name="android:background">@drawable/btn_positive_bottom</item> @@ -81,11 +83,13 @@ <style name="NegativeButton" parent="@android:style/Widget.Material.Button.Borderless.Colored"> - <item name="android:layout_width">300dp</item> - <item name="android:layout_height">56dp</item> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">wrap_content</item> <item name="android:layout_marginTop">2dp</item> <item name="android:textAllCaps">false</item> <item name="android:textSize">14sp</item> + <item name="android:layout_marginStart">32dp</item> + <item name="android:layout_marginEnd">32dp</item> <item name="android:textColor">@android:color/system_neutral1_900</item> <item name="android:layout_marginTop">4dp</item> <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item> diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java index 4154029b6d41..97016f5384f6 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java @@ -27,10 +27,8 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT; -import static com.android.companiondevicemanager.CompanionDeviceResources.MULTI_DEVICES_SUMMARIES; import static com.android.companiondevicemanager.CompanionDeviceResources.PERMISSION_TYPES; import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME; -import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILES_NAME_MULTI; import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICON; import static com.android.companiondevicemanager.CompanionDeviceResources.SUMMARIES; import static com.android.companiondevicemanager.CompanionDeviceResources.SUPPORTED_PROFILES; @@ -121,6 +119,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements private IAssociationRequestCallback mAppCallback; private ResultReceiver mCdmServiceReceiver; + // Present for application's name. + private CharSequence mAppLabel; + // Always present widgets. private TextView mTitle; private TextView mSummary; @@ -165,8 +166,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements private @Nullable RecyclerView mDeviceListRecyclerView; private @Nullable DeviceListAdapter mDeviceAdapter; - - // The recycler view is only shown for selfManaged and singleDevice association request. + // The recycler view is shown for non-null profile association request. private @Nullable RecyclerView mPermissionListRecyclerView; private @Nullable PermissionListAdapter mPermissionListAdapter; @@ -178,8 +178,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements // onActivityResult() after the association is created. private @Nullable DeviceFilterPair<?> mSelectedDevice; - private @Nullable List<Integer> mPermissionTypes; - private LinearLayoutManager mPermissionsLayoutManager = new LinearLayoutManager(this); @Override @@ -302,6 +300,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements setContentView(R.layout.activity_confirmation); + mAppLabel = appLabel; + mConstraintList = findViewById(R.id.constraint_list); mAssociationConfirmationDialog = findViewById(R.id.association_confirmation); mVendorHeader = findViewById(R.id.vendor_header); @@ -322,7 +322,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device); mSingleDeviceSpinner = findViewById(R.id.spinner_single_device); - mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick); mPermissionListRecyclerView = findViewById(R.id.permission_list); mPermissionListAdapter = new PermissionListAdapter(this); @@ -468,8 +467,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements throw new RuntimeException("Unsupported profile " + deviceProfile); } - mPermissionTypes = new ArrayList<>(); - try { vendorIcon = getVendorHeaderIcon(this, packageName, userId); vendorName = getVendorHeaderName(this, packageName, userId); @@ -486,17 +483,13 @@ public class CompanionDeviceActivity extends FragmentActivity implements } title = getHtmlFromResources(this, TITLES.get(deviceProfile), deviceName); - mPermissionTypes.addAll(PERMISSION_TYPES.get(deviceProfile)); + setupPermissionList(deviceProfile); // Summary is not needed for selfManaged dialog. mSummary.setVisibility(View.GONE); - - setupPermissionList(); - mTitle.setText(title); mVendorHeaderName.setText(vendorName); mVendorHeader.setVisibility(View.VISIBLE); - mVendorHeader.setVisibility(View.VISIBLE); mProfileIcon.setVisibility(View.GONE); mDeviceListRecyclerView.setVisibility(View.GONE); // Top and bottom borders should be gone for selfManaged dialog. @@ -509,7 +502,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements final String deviceProfile = mRequest.getDeviceProfile(); - mPermissionTypes = new ArrayList<>(); + if (!SUPPORTED_PROFILES.contains(deviceProfile)) { + throw new RuntimeException("Unsupported profile " + deviceProfile); + } CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> updateSingleDeviceUi( @@ -529,75 +524,40 @@ public class CompanionDeviceActivity extends FragmentActivity implements if (deviceFilterPairs.isEmpty()) return; mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); - // No need to show user consent dialog if it is a singleDevice - // and isSkipPrompt(true) AssociationRequest. - // See AssociationRequestsProcessor#mayAssociateWithoutPrompt. - if (mRequest.isSkipPrompt()) { - mSingleDeviceSpinner.setVisibility(View.GONE); - onUserSelectedDevice(mSelectedDevice); - return; - } - - final String deviceName = mSelectedDevice.getDisplayName(); - final Spanned title; - final Spanned summary; - final Drawable profileIcon; - if (!SUPPORTED_PROFILES.contains(deviceProfile)) { - throw new RuntimeException("Unsupported profile " + deviceProfile); - } + final Drawable profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile)); - if (deviceProfile == null) { - summary = getHtmlFromResources(this, SUMMARIES.get(null), deviceName); - mConstraintList.setVisibility(View.GONE); - } else { - summary = getHtmlFromResources( - this, SUMMARIES.get(deviceProfile), getString(R.string.device_type)); - mPermissionTypes.addAll(PERMISSION_TYPES.get(deviceProfile)); - setupPermissionList(); - } - - title = getHtmlFromResources(this, TITLES.get(deviceProfile), appLabel, deviceName); - profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile)); + updatePermissionUi(); - mTitle.setText(title); - mSummary.setText(summary); mProfileIcon.setImageDrawable(profileIcon); - mSingleDeviceSpinner.setVisibility(View.GONE); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); + mSingleDeviceSpinner.setVisibility(View.GONE); } private void initUiForMultipleDevices(CharSequence appLabel) { if (DEBUG) Log.i(TAG, "initUiFor_MultipleDevices()"); - final String deviceProfile = mRequest.getDeviceProfile(); - - final String profileName; - final String profileNameMulti; - final Spanned summary; final Drawable profileIcon; - final int summaryResourceId; + final Spanned title; + final String deviceProfile = mRequest.getDeviceProfile(); if (!SUPPORTED_PROFILES.contains(deviceProfile)) { throw new RuntimeException("Unsupported profile " + deviceProfile); } - profileName = getString(PROFILES_NAME.get(deviceProfile)); - profileNameMulti = getString(PROFILES_NAME_MULTI.get(deviceProfile)); profileIcon = getIcon(this, PROFILE_ICON.get(deviceProfile)); - summaryResourceId = MULTI_DEVICES_SUMMARIES.get(deviceProfile); if (deviceProfile == null) { - summary = getHtmlFromResources(this, summaryResourceId); + title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel); + mButtonNotAllowMultipleDevices.setText(R.string.consent_no); } else { - summary = getHtmlFromResources(this, summaryResourceId, profileName, appLabel); + title = getHtmlFromResources(this, + R.string.chooser_title, getString(PROFILES_NAME.get(deviceProfile))); } - final Spanned title = getHtmlFromResources( - this, R.string.chooser_title, profileNameMulti, appLabel); + mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked); mTitle.setText(title); - mSummary.setText(summary); mProfileIcon.setImageDrawable(profileIcon); mDeviceListRecyclerView.setAdapter(mDeviceAdapter); @@ -613,6 +573,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mDeviceAdapter.setDevices(deviceFilterPairs); }); + mSummary.setVisibility(View.GONE); // "Remove" consent button: users would need to click on the list item. mButtonAllow.setVisibility(View.GONE); mButtonNotAllow.setVisibility(View.GONE); @@ -623,11 +584,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements mMultipleDeviceSpinner.setVisibility(View.VISIBLE); } - private void onListItemClick(int position) { - if (DEBUG) Log.d(TAG, "onListItemClick() " + position); - + private void onDeviceClicked(int position) { final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position); - + // To prevent double tap on the selected device. if (mSelectedDevice != null) { if (DEBUG) Log.w(TAG, "Already selected."); return; @@ -637,7 +596,47 @@ public class CompanionDeviceActivity extends FragmentActivity implements mSelectedDevice = requireNonNull(selectedDevice); - onUserSelectedDevice(selectedDevice); + Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString()); + + updatePermissionUi(); + + mSummary.setVisibility(View.VISIBLE); + mButtonAllow.setVisibility(View.VISIBLE); + mButtonNotAllow.setVisibility(View.VISIBLE); + mDeviceListRecyclerView.setVisibility(View.GONE); + mNotAllowMultipleDevicesLayout.setVisibility(View.GONE); + } + + private void updatePermissionUi() { + final String deviceProfile = mRequest.getDeviceProfile(); + final int summaryResourceId = SUMMARIES.get(deviceProfile); + final String remoteDeviceName = mSelectedDevice.getDisplayName(); + final Spanned title = getHtmlFromResources( + this, TITLES.get(deviceProfile), mAppLabel, remoteDeviceName); + final Spanned summary; + + // No need to show permission consent dialog if it is a isSkipPrompt(true) + // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. + if (mRequest.isSkipPrompt()) { + mSingleDeviceSpinner.setVisibility(View.GONE); + onUserSelectedDevice(mSelectedDevice); + return; + } + + if (deviceProfile == null && mRequest.isSingleDevice()) { + summary = getHtmlFromResources(this, summaryResourceId, remoteDeviceName); + mConstraintList.setVisibility(View.GONE); + } else if (deviceProfile == null) { + onUserSelectedDevice(mSelectedDevice); + return; + } else { + summary = getHtmlFromResources( + this, summaryResourceId, getString(R.string.device_type)); + setupPermissionList(deviceProfile); + } + + mTitle.setText(title); + mSummary.setText(summary); } private void onPositiveButtonClick(View v) { @@ -680,8 +679,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements // initiate the layoutManager for the recyclerview, add listeners for monitoring the scrolling // and when mPermissionListRecyclerView is fully populated. // Lastly, disable the Allow and Don't allow buttons. - private void setupPermissionList() { - mPermissionListAdapter.setPermissionType(mPermissionTypes); + private void setupPermissionList(String deviceProfile) { + final List<Integer> permissionTypes = new ArrayList<>(PERMISSION_TYPES.get(deviceProfile)); + mPermissionListAdapter.setPermissionType(permissionTypes); mPermissionListRecyclerView.setAdapter(mPermissionListAdapter); mPermissionListRecyclerView.setLayoutManager(mPermissionsLayoutManager); diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java index 7aed13960b08..060c03213bcd 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceResources.java @@ -86,21 +86,11 @@ final class CompanionDeviceResources { static final Map<String, Integer> SUMMARIES; static { final Map<String, Integer> map = new ArrayMap<>(); - map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch_single_device); - map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_single_device); - map.put(null, R.string.summary_generic_single_device); - - SUMMARIES = unmodifiableMap(map); - } - - static final Map<String, Integer> MULTI_DEVICES_SUMMARIES; - static { - final Map<String, Integer> map = new ArrayMap<>(); map.put(DEVICE_PROFILE_WATCH, R.string.summary_watch); - map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses_multi_device); + map.put(DEVICE_PROFILE_GLASSES, R.string.summary_glasses); map.put(null, R.string.summary_generic); - MULTI_DEVICES_SUMMARIES = unmodifiableMap(map); + SUMMARIES = unmodifiableMap(map); } static final Map<String, Integer> PROFILES_NAME; |