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

Commit b3f4f5d3 authored by Chienyuan Huang's avatar Chienyuan Huang
Browse files

Add new API for directed advertising

Flag: com.android.bluetooth.flags.directed_advertising
Bug: 378230500
Bug: 377516681
Test: m com.andorid.btservices
Change-Id: I4e08fbb8d6ac918594422cf16a70926d14265276
parent b659e911
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -2400,6 +2400,14 @@ static AdvertiseParameters parseParams(JNIEnv* env, jobject i) {
  int8_t txPowerLevel = env->CallIntMethod(i, methodId);
  methodId = env->GetMethodID(clazz, "getOwnAddressType", "()I");
  int8_t ownAddressType = env->CallIntMethod(i, methodId);
  methodId = env->GetMethodID(clazz, "isDirected", "()Z");
  jboolean isDirected = env->CallBooleanMethod(i, methodId);
  methodId = env->GetMethodID(clazz, "isHighDutyCycle", "()Z");
  jboolean isHighDutyCycle = env->CallIntMethod(i, methodId);
  methodId = env->GetMethodID(clazz, "getPeerAddress", "()Ljava/lang/String;");
  jstring peerAddress = (jstring)env->CallObjectMethod(i, methodId);
  methodId = env->GetMethodID(clazz, "getPeerAddressType", "()I");
  int8_t peerAddressType = env->CallIntMethod(i, methodId);

  uint16_t props = 0;
  if (isConnectable) {
@@ -2408,9 +2416,12 @@ static AdvertiseParameters parseParams(JNIEnv* env, jobject i) {
  if (isScannable) {
    props |= 0x02;
  }
  if (isDiscoverable) {
  if (isDirected) {
    props |= 0x04;
  }
  if (isHighDutyCycle) {
    props |= 0x08;
  }
  if (isLegacy) {
    props |= 0x10;
  }
@@ -2434,6 +2445,9 @@ static AdvertiseParameters parseParams(JNIEnv* env, jobject i) {
  p.secondary_advertising_phy = secondaryPhy;
  p.scan_request_notification_enable = false;
  p.own_address_type = ownAddressType;
  p.peer_address = str2addr(env, peerAddress);
  p.peer_address_type = peerAddressType;
  p.discoverable = isDiscoverable;
  return p;
}

+8 −0
Original line number Diff line number Diff line
@@ -1257,6 +1257,10 @@ package android.bluetooth.le {

  public final class AdvertisingSetParameters implements android.os.Parcelable {
    method public int getOwnAddressType();
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") @Nullable public String getPeerAddress();
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") public int getPeerAddressType();
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") public boolean isDirected();
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") public boolean isHighDutyCycle();
    field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
@@ -1264,7 +1268,11 @@ package android.bluetooth.le {
  }

  public static final class AdvertisingSetParameters.Builder {
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setDirected(boolean);
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setHighDutyCycle(boolean);
    method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setPeerAddress(@NonNull String);
    method @FlaggedApi("com.android.bluetooth.flags.directed_advertising_api") @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setPeerAddressType(int);
  }

  public final class BluetoothLeAdvertiser {
+195 −4
Original line number Diff line number Diff line
@@ -16,16 +16,22 @@

package android.bluetooth.le;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice.AddressType;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.bluetooth.flags.Flags;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
 * The {@link AdvertisingSetParameters} provide a way to adjust advertising preferences for each
@@ -133,6 +139,10 @@ public final class AdvertisingSetParameters implements Parcelable {
    private final int mInterval;
    private final int mTxPowerLevel;
    private final int mOwnAddressType;
    private final boolean mIsDirected;
    private final boolean mIsHighDutyCycle;
    private final String mPeerAddress;
    private final @AddressType int mPeerAddressType;

    private AdvertisingSetParameters(
            boolean connectable,
@@ -145,7 +155,11 @@ public final class AdvertisingSetParameters implements Parcelable {
            int secondaryPhy,
            int interval,
            int txPowerLevel,
            @AddressTypeStatus int ownAddressType) {
            @AddressTypeStatus int ownAddressType,
            boolean isDirected,
            boolean isHighDutyCycle,
            String peerAddress,
            @AddressType int peerAddressType) {
        mConnectable = connectable;
        mDiscoverable = discoverable;
        mScannable = scannable;
@@ -157,6 +171,10 @@ public final class AdvertisingSetParameters implements Parcelable {
        mInterval = interval;
        mTxPowerLevel = txPowerLevel;
        mOwnAddressType = ownAddressType;
        mIsDirected = isDirected;
        mIsHighDutyCycle = isHighDutyCycle;
        mPeerAddress = peerAddress;
        mPeerAddressType = peerAddressType;
    }

    private AdvertisingSetParameters(Parcel in) {
@@ -171,6 +189,10 @@ public final class AdvertisingSetParameters implements Parcelable {
        mTxPowerLevel = in.readInt();
        mOwnAddressType = in.readInt();
        mDiscoverable = in.readInt() != 0;
        mIsDirected = in.readBoolean();
        mIsHighDutyCycle = in.readBoolean();
        mPeerAddress = in.readString();
        mPeerAddressType = in.readInt();
    }

    /** Returns whether the advertisement will be connectable. */
@@ -232,6 +254,50 @@ public final class AdvertisingSetParameters implements Parcelable {
        return mOwnAddressType;
    }

    /**
     * @return Whether the advertisement is directed
     * @hide This API is not publicly available as it is mainly intended for accessory devices
     *     running Android to broadcast their availability and which can thus leverage system APIs.
     */
    @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
    @SystemApi
    public boolean isDirected() {
        return mIsDirected;
    }

    /**
     * @return Whether the advertisement is high duty cycle or not
     * @hide This API is not publicly available as it is mainly intended for accessory devices
     *     running Android to broadcast their availability and which can thus leverage system APIs.
     */
    @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
    @SystemApi
    public boolean isHighDutyCycle() {
        return mIsHighDutyCycle;
    }

    /**
     * @return Peer address for directed advertising
     * @hide This API is not publicly available as it is mainly intended for accessory devices
     *     running Android to broadcast their availability and which can thus leverage system APIs.
     */
    @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
    @SystemApi
    public @Nullable String getPeerAddress() {
        return mPeerAddress;
    }

    /**
     * @return Peer address type for directed advertising
     * @hide This API is not publicly available as it is mainly intended for accessory devices
     *     running Android to broadcast their availability and which can thus leverage system APIs.
     */
    @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
    @SystemApi
    public @AddressType int getPeerAddressType() {
        return mPeerAddressType;
    }

    @Override
    public String toString() {
        return "AdvertisingSetParameters [connectable="
@@ -254,6 +320,14 @@ public final class AdvertisingSetParameters implements Parcelable {
                + mTxPowerLevel
                + ", ownAddressType="
                + mOwnAddressType
                + ", isDirected="
                + mIsDirected
                + ", isHighDutyCycle="
                + mIsHighDutyCycle
                + ", peerAddress="
                + mPeerAddress
                + ", peerAddressType="
                + mPeerAddressType
                + "]";
    }

@@ -275,6 +349,10 @@ public final class AdvertisingSetParameters implements Parcelable {
        dest.writeInt(mTxPowerLevel);
        dest.writeInt(mOwnAddressType);
        dest.writeInt(mDiscoverable ? 1 : 0);
        dest.writeBoolean(mIsDirected);
        dest.writeBoolean(mIsHighDutyCycle);
        android.bluetooth.BluetoothUtils.writeStringToParcel(dest, mPeerAddress);
        dest.writeInt(mPeerAddressType);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<AdvertisingSetParameters>
@@ -304,6 +382,10 @@ public final class AdvertisingSetParameters implements Parcelable {
        private int mInterval = INTERVAL_LOW;
        private int mTxPowerLevel = TX_POWER_MEDIUM;
        private int mOwnAddressType = ADDRESS_TYPE_DEFAULT;
        private boolean mIsDirected = false;
        private boolean mIsHighDutyCycle = false;
        private String mPeerAddress = null;
        private @AddressType int mPeerAddressType = BluetoothDevice.ADDRESS_TYPE_PUBLIC;

        /**
         * Set whether the advertisement type should be connectable or non-connectable. Legacy
@@ -481,6 +563,85 @@ public final class AdvertisingSetParameters implements Parcelable {
            return this;
        }

        /**
         * Set whether the advertising is a directed advertising.
         *
         * @param isDirected Controls whether the advertising is directed or not
         * @hide This API is not publicly available as it is mainly intended for accessory devices
         *     running Android to broadcast their availability and which can thus leverage system
         *     APIs.
         */
        @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
        @SystemApi
        public @NonNull Builder setDirected(boolean isDirected) {
            mIsDirected = isDirected;
            return this;
        }

        /**
         * Set whether the advertising is high duty cycle or not.
         *
         * @param isHighDutyCycle Controls whether the advertising high duty cycle or not
         * @hide This API is not publicly available as it is mainly intended for accessory devices
         *     running Android to broadcast their availability and which can thus leverage system
         *     APIs.
         */
        @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
        @SystemApi
        public @NonNull Builder setHighDutyCycle(boolean isHighDutyCycle) {
            mIsHighDutyCycle = isHighDutyCycle;
            return this;
        }

        /**
         * Set peer address for directed advertising.
         *
         * @param peerAddress peer address for the directed advertising
         * @throws IllegalArgumentException peer address is invalid
         * @hide This API is not publicly available as it is mainly intended for accessory devices
         *     running Android to broadcast their availability and which can thus leverage system
         *     APIs.
         */
        @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
        @SystemApi
        public @NonNull Builder setPeerAddress(@NonNull String peerAddress) {
            Objects.requireNonNull(peerAddress, "peerAddress is null");
            if (!BluetoothAdapter.checkBluetoothAddress(peerAddress)) {
                throw new IllegalArgumentException(
                        peerAddress + " is not a valid Bluetooth address");
            }
            mPeerAddress = peerAddress;
            return this;
        }

        /**
         * Set peer address type for directed advertising.
         *
         * @param peerAddressType peer address type for the directed advertising
         * @throws IllegalArgumentException if {@code peerAddressType} is invalid
         * @hide This API is not publicly available as it is mainly intended for accessory devices
         *     running Android to broadcast their availability and which can thus leverage system
         *     APIs.
         */
        @FlaggedApi(Flags.FLAG_DIRECTED_ADVERTISING_API)
        @SystemApi
        public @NonNull Builder setPeerAddressType(@AddressType int peerAddressType) {
            switch (peerAddressType) {
                case BluetoothDevice.ADDRESS_TYPE_PUBLIC:
                case BluetoothDevice.ADDRESS_TYPE_RANDOM:
                    mPeerAddressType = peerAddressType;
                    break;
                case BluetoothDevice.ADDRESS_TYPE_UNKNOWN:
                case BluetoothDevice.ADDRESS_TYPE_ANONYMOUS:
                    throw new IllegalArgumentException(
                            "unsupported peer address type " + peerAddressType);
                default:
                    throw new IllegalArgumentException(
                            "unknown peer address type " + peerAddressType);
            }
            return this;
        }

        /**
         * Build the {@link AdvertisingSetParameters} object.
         *
@@ -492,9 +653,25 @@ public final class AdvertisingSetParameters implements Parcelable {
                    throw new IllegalArgumentException("Legacy advertising can't be anonymous");
                }

                if (mConnectable && !mScannable) {
                if (mIsDirected && !mConnectable) {
                    throw new IllegalStateException(
                            "Legacy directed advertising must be connectable");
                }

                if (mIsDirected && mScannable) {
                    throw new IllegalStateException(
                            "Legacy directed advertising can't be scannable");
                }

                if (!mIsDirected && mIsHighDutyCycle) {
                    throw new IllegalStateException(
                            "Non-directed legacy advertising can't be high duty cycle");
                }

                if (!mIsDirected && mConnectable && !mScannable) {
                    throw new IllegalStateException(
                            "Legacy advertisement can't be connectable and non-scannable");
                            "Non-directed legacy advertising can't be connectable and"
                                    + " non-scannable");
                }

                if (mIncludeTxPower) {
@@ -511,6 +688,16 @@ public final class AdvertisingSetParameters implements Parcelable {
                    throw new IllegalStateException(
                            "Advertising can't be both connectable and anonymous");
                }

                if (mIsHighDutyCycle) {
                    throw new IllegalStateException(
                            "Non-legacy advertising can't be high duty cycle");
                }
            }

            if (mIsDirected && mPeerAddress == null) {
                throw new IllegalStateException(
                        "Peer address should not be null for directed advertising");
            }

            return new AdvertisingSetParameters(
@@ -524,7 +711,11 @@ public final class AdvertisingSetParameters implements Parcelable {
                    mSecondaryPhy,
                    mInterval,
                    mTxPowerLevel,
                    mOwnAddressType);
                    mOwnAddressType,
                    mIsDirected,
                    mIsHighDutyCycle,
                    mPeerAddress,
                    mPeerAddressType);
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ bool AdvertisingConfigFromProto(const AdvertisingConfig& config_proto,
    case AdvertisingType::ADV_DIRECT_IND_HIGH: {
      config->connectable = true;
      config->directed = true;
      config->high_duty_directed_connectable = true;
      config->high_duty_cycle = true;
    } break;
    case AdvertisingType::ADV_SCAN_IND: {
      config->scannable = true;
@@ -150,7 +150,7 @@ bool ExtendedAdvertisingConfigFromProto(const ExtendedAdvertisingConfig& config_
  config->connectable = config_proto.connectable();
  config->scannable = config_proto.scannable();
  config->directed = config_proto.directed();
  config->high_duty_directed_connectable = config_proto.high_duty_directed_connectable();
  config->high_duty_cycle = config_proto.high_duty_directed_connectable();
  config->legacy_pdus = config_proto.legacy_pdus();
  config->anonymous = config_proto.anonymous();
  config->include_tx_power = config_proto.include_tx_power();
+3 −3
Original line number Diff line number Diff line
@@ -936,7 +936,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
          LegacyAdvertisingEventProperties legacy_properties =
                  LegacyAdvertisingEventProperties::ADV_IND;
          if (config.connectable && config.directed) {
            if (config.high_duty_directed_connectable) {
            if (config.high_duty_cycle) {
              legacy_properties = LegacyAdvertisingEventProperties::ADV_DIRECT_IND_HIGH;
            } else {
              legacy_properties = LegacyAdvertisingEventProperties::ADV_DIRECT_IND_LOW;
@@ -965,7 +965,7 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
          extended_properties.connectable_ = config.connectable;
          extended_properties.scannable_ = config.scannable;
          extended_properties.directed_ = config.directed;
          extended_properties.high_duty_cycle_ = config.high_duty_directed_connectable;
          extended_properties.high_duty_cycle_ = config.high_duty_cycle;
          extended_properties.legacy_ = false;
          extended_properties.anonymous_ = config.anonymous;
          extended_properties.tx_power_ = config.include_tx_power;
@@ -1859,7 +1859,7 @@ void LeAdvertisingManager::ExtendedCreateAdvertiser(
             AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
      return;
    }
    if (config.high_duty_directed_connectable) {
    if (config.high_duty_cycle) {
      log::info("Extended advertising PDUs can not be high duty cycle");
      CallOn(pimpl_.get(), &impl::start_advertising_fail, reg_id,
             AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
Loading