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

Commit 9e74a4c7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Apply bullet permission UI to multiple device dialog" into udc-qpr-dev am: 1ae8e217

parents fd9beaa5 1ae8e217
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@
                        android:visibility="gone"
                        android:duplicateParentState="true"
                        android:clickable="false"
                        android:text="@string/consent_no" />
                        android:text="@string/consent_cancel" />

                </LinearLayout>

+11 −14
Original line number Diff line number Diff line
@@ -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 &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%2$s</xliff:g>&lt;/strong&gt;</string>
    <string name="chooser_title_non_profile">Choose a device to be managed by &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt;</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 &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; to manage &lt;strong&gt;<xliff:g id="device_name" example="Glasses">%2$s</xliff:g>&lt;/strong&gt;?</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 ================= -->

@@ -96,9 +93,6 @@
    <!-- A noun for a companion device with unspecified profile (type) [CHAR LIMIT=30] -->
    <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>

@@ -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>

+8 −4
Original line number Diff line number Diff line
@@ -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>
+67 −67
Original line number Diff line number Diff line
@@ -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);

+2 −12
Original line number Diff line number Diff line
@@ -84,23 +84,13 @@ 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;