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

Commit 9dc349d7 authored by Aaron Kling's avatar Aaron Kling Committed by Luca Stefani
Browse files

BondStateMachine: Allow skipping confirm for some remotes

When pairing two of the Nvidia Shield accessories, a popup would show up
stating that the accessory was an incoming pairing request and needs to
be accepted. The official Nvidia firmware has a whitelist of remotes
that skip this confirmation if pairing request is marked as originating
from the Android device. This change takes a similar approach, but in a
more flexible manner. The main intent is to allow these accessories to
be paired via the pairing intent, which needs to complete with no user
interaction. Previously, the popup would prevent this from succeeding.

Change-Id: Ib5a0226858f5745a20e4cd166500aecdcf1f3354
parent 52d9495b
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.Bundle;
import android.os.Message;
import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
@@ -48,6 +49,7 @@ import com.android.internal.util.StateMachine;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -384,7 +386,37 @@ final class BondStateMachine extends StateMachine {
        return false;
    }

    // Defining these properly would break current api
    private static int PERIPHERAL_GAMEPAD = BluetoothClass.Device.Major.PERIPHERAL | 0x08;
    private static int PERIPHERAL_REMOTE = BluetoothClass.Device.Major.PERIPHERAL | 0x0C;

    private static List<Pair<String, Integer>> accConfirmSkip = new ArrayList<>();

    static {
        // Jarvis, SHIELD Remote 2015
        accConfirmSkip.add(new Pair<>("SHIELD Remote", PERIPHERAL_REMOTE));
        // Thunderstrike, SHIELD Controller 2017
        accConfirmSkip.add(new Pair<>("NVIDIA Controller v01.04", PERIPHERAL_GAMEPAD));
    };

    private boolean isSkipConfirmationAccessory(BluetoothDevice device) {
        for (Pair<String, Integer> entry : accConfirmSkip) {
            if (device.getName().equals(entry.first)
                    && device.getBluetoothClass().getDeviceClass() == entry.second) {
                return true;
            }
        }

        return false;
    }

    private void sendDisplayPinIntent(byte[] address, Optional<Integer> maybePin, int variant) {
        BluetoothDevice device = mRemoteDevices.getDevice(address);
        if (device != null && device.isBondingInitiatedLocally()
                && isSkipConfirmationAccessory(device)) {
            device.setPairingConfirmation(true);
            return;
        }
        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevices.getDevice(address));
        maybePin.ifPresent(pin -> intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin));