content: package com.uriio.beacons.ble;
  
  import android.annotation.TargetApi;
  import android.bluetooth.le.AdvertiseData;
  import android.os.Build;
  import android.os.ParcelUuid;
  
  import com.uriio.beacons.ble.gatt.EddystoneGattService;
  
  /**
  * Advertise as an Eddystone beacon
  */
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public class EddystoneAdvertiser extends Advertiser {
      // 16-bit 0xFEAA expanded to a BLE 128-bit UUID
      private static final ParcelUuid EDDYSTONE_SERVICE_UUID = parcelUuidFromShortUUID(0xFEAA);
  
      public static final byte FRAME_UID = 0x00;
      public static final byte FRAME_URL = 0x10;
      public static final byte FRAME_TLM = 0x20;
      public static final byte FRAME_EID = 0x30;
  
      private final AdvertiseData mAdvertiseData;
      private AdvertiseData mAdvertiseScanResponse = null;
      private final byte[] mServiceData;
  
      /**
       * Creates an Eddystone BLE advertiser. It does not start any actual transmission.
       * @param frameData              Frame data (without service data frame type or TX power bytes)
       * @param pos                    Frame data offset
       * @param len                    Frame data size
       */
      public EddystoneAdvertiser(SettingsProvider provider, byte frameType, byte[] frameData,
                                 int pos, int len)
      {
          super(provider);
  
          mServiceData = new byte[2 + len];
  
          mServiceData[0] = frameType;
          mServiceData[1] = FRAME_TLM == frameType ? 0
                  : AdvertisersManager.getZeroDistanceTxPower(provider.getTxPowerLevel());
          System.arraycopy(frameData, pos, mServiceData, 2, len);
  
          // an advertisement packet can have at most 31 bytes
          mAdvertiseData = new AdvertiseData.Builder()
                  .setIncludeDeviceName(false)
                  .setIncludeTxPowerLevel(false)
                  .addServiceData(EDDYSTONE_SERVICE_UUID, mServiceData)
                  .addServiceUuid(EDDYSTONE_SERVICE_UUID)
                  .build();
  
          if (provider.isConnectable()) {
              mAdvertiseScanResponse = new AdvertiseData.Builder()
                      .setIncludeDeviceName(true)
                      .setIncludeTxPowerLevel(false)  // allows 3 more bytes for device name
                      .addServiceUuid(new ParcelUuid(EddystoneGattService.UUID_EDDYSTONE_GATT_SERVICE))
                      .build();
          }
      }
  
      @Override
      public AdvertiseData getAdvertiseData() {
          return mAdvertiseData;
      }
  
      @Override
      public AdvertiseData getAdvertiseScanResponse() {
          return mAdvertiseScanResponse;
      }
  
      @Override
      public String getAdvertisedLocalName() {
          if (null != mAdvertiseScanResponse && mAdvertiseScanResponse.getIncludeDeviceName()) {
              // fix device name so it fits into the scan record
              int maxNameLen = 8 + 3;  // we've got 3 bytes more if TX is not advertised
              return Build.MODEL.length() <= maxNameLen ? Build.MODEL : Build.MODEL.substring(0, maxNameLen);
          }
  
          return null;
      }
  
      public byte[] getServiceData() {
          return mServiceData;
      }
  }