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

Commit b6917b09 authored by Evan Chen's avatar Evan Chen
Browse files

Fix RecyclerView crash in device discovery list

Resolves an IndexOutOfBoundsException when updating the list of
discovered companion devices.

The adapter was using a shared, mutable list reference, causing its
internal state to be out of sync.

The fix is to have the discovery service create a new list snapshot on
each update and for the adapter to correctly calculate diffs for
notifyItemRangeInserted().

Test: CTS
Fix: 425323417
Flag: EXEMPT bugfix
Change-Id: I90a445b163ac1c02d762ad273e5250b21167180e
parent 71348c49
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -393,7 +393,7 @@ public class CompanionDeviceDiscoveryService extends Service {
            // First: make change.
            mDevicesFound.add(device);
            // Then: notify observers.
            sScanResultsLiveData.setValue(mDevicesFound);
            sScanResultsLiveData.setValue(new ArrayList<>(mDevicesFound));
            // Stop discovery when there's one device found for singleDevice.
            if (mStopAfterFirstMatch) {
                stopDiscoveryAndFinish();
@@ -408,7 +408,7 @@ public class CompanionDeviceDiscoveryService extends Service {
            // First: make change.
            mDevicesFound.remove(device);
            // Then: notify observers.
            sScanResultsLiveData.setValue(mDevicesFound);
            sScanResultsLiveData.setValue(new ArrayList<>(mDevicesFound));
        });
    }

+9 −1
Original line number Diff line number Diff line
@@ -100,8 +100,16 @@ class DeviceListAdapter extends RecyclerView.Adapter<DeviceListAdapter.ViewHolde
    }

    void setDevices(List<DeviceFilterPair<?>> devices) {
        final int oldSize = mDevices == null ? 0 : mDevices.size();
        mDevices = devices;
        notifyItemRangeInserted(devices.size(), mDevices.size());
        final int newSize = mDevices.size();
        if (newSize > oldSize) {
            notifyItemRangeInserted(oldSize, newSize - oldSize);
        } else if (newSize < oldSize) {
            // Items were removed. simply refresh the whole list.
            notifyDataSetChanged();
        }
        // If newSize == oldSize, nothing has changed, so no notification is needed.
    }

    static class ViewHolder extends RecyclerView.ViewHolder {