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

Commit 4653665d authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8887382 from 9c20f715 to tm-qpr1-release

Change-Id: I03bb93fedf240cb7e3fceedb046844d72cd11449
parents 750deafe 9c20f715
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ import android.util.Log;

import com.android.bluetooth.Utils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.obex.HeaderSet;

import java.io.IOException;

/**
 * Proxy class for method calls to help with unit testing
@@ -63,11 +66,26 @@ public class BluetoothPbapMethodProxy {
    }

    /**
     * Return the result of {@link ContentResolver#query(Uri, String[], String, String[], String)}.
     * Proxies {@link ContentResolver#query(Uri, String[], String, String[], String)}.
     */
    public Cursor contentResolverQuery(ContentResolver contentResolver, final Uri contentUri,
            final String[] projection, final String selection, final String[] selectionArgs,
            final String sortOrder) {
        return contentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder);
    }

    /**
     * Proxies {@link HeaderSet#setHeader}.
     */
    public void setHeader(HeaderSet headerSet, int headerId, Object headerValue)
            throws IOException {
        headerSet.setHeader(headerId, headerValue);
    }

    /**
     * Proxies {@link HeaderSet#getHeader}.
     */
    public Object getHeader(HeaderSet headerSet, int headerId) throws IOException {
        return headerSet.getHeader(headerId);
    }
}
+9 −5
Original line number Diff line number Diff line
@@ -223,6 +223,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {

    private PbapStateMachine mStateMachine;

    private BluetoothPbapMethodProxy mPbapMethodProxy;

    private enum ContactsType {
        TYPE_PHONEBOOK , TYPE_SIM ;
    }
@@ -251,6 +253,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        mVcardManager = new BluetoothPbapVcardManager(mContext);
        mVcardSimManager = new BluetoothPbapSimVcardManager(mContext);
        mStateMachine = stateMachine;
        mPbapMethodProxy = BluetoothPbapMethodProxy.getInstance();
    }

    @Override
@@ -260,7 +263,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        }
        notifyUpdateWakeLock();
        try {
            byte[] uuid = (byte[]) request.getHeader(HeaderSet.TARGET);
            byte[] uuid = (byte[]) mPbapMethodProxy.getHeader(request, HeaderSet.TARGET);
            if (uuid == null) {
                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
            }
@@ -278,19 +281,19 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
                    return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
                }
            }
            reply.setHeader(HeaderSet.WHO, uuid);
            mPbapMethodProxy.setHeader(reply, HeaderSet.WHO, uuid);
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
        }

        try {
            byte[] remote = (byte[]) request.getHeader(HeaderSet.WHO);
            byte[] remote = (byte[]) mPbapMethodProxy.getHeader(request, HeaderSet.WHO);
            if (remote != null) {
                if (D) {
                    Log.d(TAG, "onConnect(): remote=" + Arrays.toString(remote));
                }
                reply.setHeader(HeaderSet.TARGET, remote);
                mPbapMethodProxy.setHeader(reply, HeaderSet.TARGET, remote);
            }
        } catch (IOException e) {
            Log.e(TAG, e.toString());
@@ -300,7 +303,8 @@ public class BluetoothPbapObexServer extends ServerRequestHandler {
        try {
            byte[] appParam = null;
            mConnAppParamValue = new AppParamValue();
            appParam = (byte[]) request.getHeader(HeaderSet.APPLICATION_PARAMETER);
            appParam = (byte[])
                    mPbapMethodProxy.getHeader(request, HeaderSet.APPLICATION_PARAMETER);
            if ((appParam != null) && !parseApplicationParameter(appParam, mConnAppParamValue)) {
                return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
            }
+299 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.pbap;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import android.os.Handler;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.obex.HeaderSet;
import com.android.obex.Operation;
import com.android.obex.ResponseCodes;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import java.io.IOException;
import java.io.OutputStream;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BluetoothPbapObexServerTest {

    @Mock Handler mMockHandler;
    @Mock PbapStateMachine mMockStateMachine;

    @Spy
    BluetoothPbapMethodProxy mPbapMethodProxy = BluetoothPbapMethodProxy.getInstance();

    BluetoothPbapObexServer mServer;

    // 128 bit UUID for PBAP
    private static final byte[] PBAP_TARGET_UUID = new byte[] {
            0x79,
            0x61,
            0x35,
            (byte) 0xf0,
            (byte) 0xf0,
            (byte) 0xc5,
            0x11,
            (byte) 0xd8,
            0x09,
            0x66,
            0x08,
            0x00,
            0x20,
            0x0c,
            (byte) 0x9a,
            0x66
    };

    private static final byte[] WRONG_UUID = new byte[] {
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
            0x00,
    };

    private static final byte[] WRONG_LENGTH_UUID = new byte[] {
            0x79,
            0x61,
            0x35,
    };

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        BluetoothPbapMethodProxy.setInstanceForTesting(mPbapMethodProxy);
        mServer = new BluetoothPbapObexServer(
                mMockHandler, InstrumentationRegistry.getTargetContext(), mMockStateMachine);
    }

    @After
    public void tearDown() throws Exception {
        BluetoothPbapMethodProxy.setInstanceForTesting(null);
    }

    @Test
    public void testOnConnect_whenUuidIsNull() {
        // Create an empty header set.
        HeaderSet request = new HeaderSet();
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE);
    }

    @Test
    public void testOnConnect_whenUuidLengthIsWrong() {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, WRONG_LENGTH_UUID);
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE);
    }

    @Test
    public void testOnConnect_whenUuidIsWrong() {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, WRONG_UUID);
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE);
    }

    @Test
    public void testOnConnect_whenIoExceptionIsThrownFromSettingWhoHeader() throws Exception {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, PBAP_TARGET_UUID);

        HeaderSet reply = new HeaderSet();
        doThrow(IOException.class).when(mPbapMethodProxy)
                .setHeader(eq(reply), eq(HeaderSet.WHO), any());

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR);
    }

    @Test
    public void testOnConnect_whenIoExceptionIsThrownFromSettingTargetHeader() throws Exception {
        HeaderSet request = new HeaderSet();
        byte[] whoHeader = new byte[] {0x00, 0x01, 0x02};
        request.setHeader(HeaderSet.WHO, whoHeader);
        request.setHeader(HeaderSet.TARGET, PBAP_TARGET_UUID);

        HeaderSet reply = new HeaderSet();
        doThrow(IOException.class).when(mPbapMethodProxy)
                .setHeader(eq(reply), eq(HeaderSet.TARGET), any());

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR);
    }

    @Test
    public void testOnConnect_whenIoExceptionIsThrownFromGettingApplicationParameterHeader()
            throws Exception {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, PBAP_TARGET_UUID);
        HeaderSet reply = new HeaderSet();

        doThrow(IOException.class).when(mPbapMethodProxy)
                .getHeader(request, HeaderSet.APPLICATION_PARAMETER);

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR);
    }

    @Test
    public void testOnConnect_whenApplicationParameterIsWrong() {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, PBAP_TARGET_UUID);
        HeaderSet reply = new HeaderSet();

        byte[] badApplicationParameter = new byte[] {0x00, 0x01, 0x02};
        request.setHeader(HeaderSet.APPLICATION_PARAMETER, badApplicationParameter);

        assertThat(mServer.onConnect(request, reply))
                .isEqualTo(ResponseCodes.OBEX_HTTP_BAD_REQUEST);
    }

    @Test
    public void testOnConnect_success() {
        HeaderSet request = new HeaderSet();
        request.setHeader(HeaderSet.TARGET, PBAP_TARGET_UUID);
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onConnect(request, reply)).isEqualTo(ResponseCodes.OBEX_HTTP_OK);
    }

    @Test
    public void testOnDisconnect() throws Exception {
        HeaderSet request = new HeaderSet();
        HeaderSet response = new HeaderSet();

        mServer.onDisconnect(request, response);

        assertThat(response.getResponseCode()).isEqualTo(ResponseCodes.OBEX_HTTP_OK);
    }

    @Test
    public void testOnAbort() throws Exception {
        HeaderSet request = new HeaderSet();
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onAbort(request, reply)).isEqualTo(ResponseCodes.OBEX_HTTP_OK);
        assertThat(mServer.sIsAborted).isTrue();
    }

    @Test
    public void testOnPut_notSupported() {
        Operation operation = mock(Operation.class);
        assertThat(mServer.onPut(operation)).isEqualTo(ResponseCodes.OBEX_HTTP_BAD_REQUEST);
    }

    @Test
    public void testOnDelete_notSupported() {
        HeaderSet request = new HeaderSet();
        HeaderSet reply = new HeaderSet();

        assertThat(mServer.onDelete(request, reply)).isEqualTo(ResponseCodes.OBEX_HTTP_BAD_REQUEST);
    }

    @Test
    public void testOnClose() {
        mServer.onClose();
        verify(mMockStateMachine).sendMessage(PbapStateMachine.DISCONNECT);
    }

    @Test
    public void testCloseStream_success() throws Exception{
        OutputStream outputStream = mock(OutputStream.class);
        Operation operation = mock(Operation.class);

        assertThat(BluetoothPbapObexServer.closeStream(outputStream, operation)).isTrue();
        verify(outputStream).close();
        verify(operation).close();
    }

    @Test
    public void testCloseStream_failOnClosingOutputStream() throws Exception {
        OutputStream outputStream = mock(OutputStream.class);
        doThrow(IOException.class).when(outputStream).close();
        Operation operation = mock(Operation.class);

        assertThat(BluetoothPbapObexServer.closeStream(outputStream, operation)).isFalse();
    }

    @Test
    public void testCloseStream_failOnClosingOperation() throws Exception {
        OutputStream outputStream = mock(OutputStream.class);
        Operation operation = mock(Operation.class);
        doThrow(IOException.class).when(operation).close();

        assertThat(BluetoothPbapObexServer.closeStream(outputStream, operation)).isFalse();
    }

    @Test
    public void testOnAuthenticationFailure() {
        byte[] userName = {0x57, 0x68, 0x79};
        try {
            mServer.onAuthenticationFailure(userName);
        } catch (Exception ex) {
            assertWithMessage("Exception should not happen.").fail();
        }
    }

    @Test
    public void testLogHeader() throws Exception{
        HeaderSet headerSet = new HeaderSet();
        try {
            BluetoothPbapObexServer.logHeader(headerSet);
        } catch (Exception ex) {
            assertWithMessage("Exception should not happen.").fail();
        }
    }
}
+65 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "module.h"
#include "os/handler.h"
#include "os/log.h"
#include "storage/storage_module.h"

namespace bluetooth {
namespace hci {
@@ -235,12 +236,14 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
      hci::HciLayer* hci_layer,
      hci::Controller* controller,
      hci::AclManager* acl_manager,
      hci::VendorSpecificEventManager* vendor_specific_event_manager) {
      hci::VendorSpecificEventManager* vendor_specific_event_manager,
      storage::StorageModule* storage_module) {
    module_handler_ = handler;
    hci_layer_ = hci_layer;
    controller_ = controller;
    acl_manager_ = acl_manager;
    vendor_specific_event_manager_ = vendor_specific_event_manager;
    storage_module_ = storage_module;
    le_address_manager_ = acl_manager->GetLeAddressManager();
    le_scanning_interface_ = hci_layer_->GetLeScanningInterface(
        module_handler_->BindOn(this, &LeScanningManager::impl::handle_scan_results));
@@ -711,6 +714,17 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
        module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
  }

  bool is_bonded(Address target_address) {
    for (auto device : storage_module_->GetBondedDevices()) {
      if (device.GetAddress() == target_address) {
        LOG_DEBUG("Addresses match!");
        return true;
      }
    }
    LOG_DEBUG("Addresse DON'Ts match!");
    return false;
  }

  void scan_filter_parameter_setup(
      ApcfAction action, uint8_t filter_index, AdvertisingFilterParameter advertising_filter_parameter) {
    if (!is_filter_support_) {
@@ -718,6 +732,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
      return;
    }

    auto entry = remove_me_later_map_.find(filter_index);
    switch (action) {
      case ApcfAction::ADD:
        le_scanning_interface_->EnqueueCommand(
@@ -740,11 +755,33 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
        le_scanning_interface_->EnqueueCommand(
            LeAdvFilterDeleteFilteringParametersBuilder::Create(filter_index),
            module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));

        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        break;
      case ApcfAction::CLEAR:
        le_scanning_interface_->EnqueueCommand(
            LeAdvFilterClearFilteringParametersBuilder::Create(),
            module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));

        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        break;
      default:
        LOG_ERROR("Unknown action type: %d", (uint16_t)action);
@@ -796,6 +833,8 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
    }
  }

  std::unordered_map<uint8_t, AddressWithType> remove_me_later_map_;

  void update_address_filter(
      ApcfAction action,
      uint8_t filter_index,
@@ -823,14 +862,35 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
              action, filter_index, address, ApcfApplicationAddressType::NOT_APPLICABLE),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
      if (!is_empty_128bit(irk)) {
        // If an entry exists for this filter index, replace data because the filter has been
        // updated.
        auto entry = remove_me_later_map_.find(filter_index);
        // IRK Scanning
        if (entry != remove_me_later_map_.end()) {
          // Don't want to remove for a bonded device
          if (!is_bonded(entry->second.GetAddress())) {
            le_address_manager_->RemoveDeviceFromResolvingList(
                static_cast<PeerAddressType>(entry->second.GetAddressType()), entry->second.GetAddress());
          }
          remove_me_later_map_.erase(filter_index);
        }

        // Now replace it with a new one
        std::array<uint8_t, 16> empty_irk;
        le_address_manager_->AddDeviceToResolvingList(
            static_cast<PeerAddressType>(address_type), address, irk, empty_irk);
        remove_me_later_map_.emplace(filter_index, AddressWithType(address, static_cast<AddressType>(address_type)));
      }
    } else {
      le_scanning_interface_->EnqueueCommand(
          LeAdvFilterClearBroadcasterAddressBuilder::Create(filter_index),
          module_handler_->BindOnceOn(this, &impl::on_advertising_filter_complete));
      auto entry = remove_me_later_map_.find(filter_index);
      if (entry != remove_me_later_map_.end()) {
        // TODO(optedoblivion): If not bonded
        le_address_manager_->RemoveDeviceFromResolvingList(static_cast<PeerAddressType>(address_type), address);
        remove_me_later_map_.erase(filter_index);
      }
    }
  }

@@ -1444,6 +1504,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
  hci::Controller* controller_;
  hci::AclManager* acl_manager_;
  hci::VendorSpecificEventManager* vendor_specific_event_manager_;
  storage::StorageModule* storage_module_;
  hci::LeScanningInterface* le_scanning_interface_;
  hci::LeAddressManager* le_address_manager_;
  bool address_manager_registered_ = false;
@@ -1502,6 +1563,7 @@ void LeScanningManager::ListDependencies(ModuleList* list) const {
  list->add<hci::VendorSpecificEventManager>();
  list->add<hci::Controller>();
  list->add<hci::AclManager>();
  list->add<storage::StorageModule>();
}

void LeScanningManager::Start() {
@@ -1510,7 +1572,8 @@ void LeScanningManager::Start() {
      GetDependency<hci::HciLayer>(),
      GetDependency<hci::Controller>(),
      GetDependency<AclManager>(),
      GetDependency<VendorSpecificEventManager>());
      GetDependency<VendorSpecificEventManager>(),
      GetDependency<storage::StorageModule>());
}

void LeScanningManager::Stop() {