content: /*
   * Copyright (C) 2013 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 android.bluetooth;
  
  import android.annotation.UnsupportedAppUsage;
  import android.os.Parcel;
  import android.os.ParcelUuid;
  import android.os.Parcelable;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.UUID;
  
  /**
   * Represents a Bluetooth GATT Service
   *
   * <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
   * as well as referenced services.
   */
  public class BluetoothGattService implements Parcelable {
  
      /**
       * Primary service
       */
      public static final int SERVICE_TYPE_PRIMARY = 0;
  
      /**
       * Secondary service (included by primary services)
       */
      public static final int SERVICE_TYPE_SECONDARY = 1;
  
  
      /**
       * The remote device his service is associated with.
       * This applies to client applications only.
       *
       * @hide
       */
      @UnsupportedAppUsage
      protected BluetoothDevice mDevice;
  
      /**
       * The UUID of this service.
       *
       * @hide
       */
      protected UUID mUuid;
  
      /**
       * Instance ID for this service.
       *
       * @hide
       */
      protected int mInstanceId;
  
      /**
       * Handle counter override (for conformance testing).
       *
       * @hide
       */
      protected int mHandles = 0;
  
      /**
       * Service type (Primary/Secondary).
       *
       * @hide
       */
      protected int mServiceType;
  
      /**
       * List of characteristics included in this service.
       */
      protected List<BluetoothGattCharacteristic> mCharacteristics;
  
      /**
       * List of included services for this service.
       */
      protected List<BluetoothGattService> mIncludedServices;
  
      /**
       * Whether the service uuid should be advertised.
       */
      private boolean mAdvertisePreferred;
  
      /**
       * Create a new BluetoothGattService.
       * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
       *
       * @param uuid The UUID for this service
       * @param serviceType The type of this service,
       * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY}
       * or {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
       */
      public BluetoothGattService(UUID uuid, int serviceType) {
          mDevice = null;
          mUuid = uuid;
          mInstanceId = 0;
          mServiceType = serviceType;
          mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
          mIncludedServices = new ArrayList<BluetoothGattService>();
      }
  
      /**
       * Create a new BluetoothGattService
       *
       * @hide
       */
      /*package*/ BluetoothGattService(BluetoothDevice device, UUID uuid,
              int instanceId, int serviceType) {
          mDevice = device;
          mUuid = uuid;
          mInstanceId = instanceId;
          mServiceType = serviceType;
          mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
          mIncludedServices = new ArrayList<BluetoothGattService>();
      }
  
      /**
       * Create a new BluetoothGattService
       *
       * @hide
       */
      public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
          mDevice = null;
          mUuid = uuid;
          mInstanceId = instanceId;
          mServiceType = serviceType;
          mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
          mIncludedServices = new ArrayList<BluetoothGattService>();
      }
  
      /**
       * @hide
       */
      public int describeContents() {
          return 0;
      }
  
      @Override
      public void writeToParcel(Parcel out, int flags) {
          out.writeParcelable(new ParcelUuid(mUuid), 0);
          out.writeInt(mInstanceId);
          out.writeInt(mServiceType);
          out.writeTypedList(mCharacteristics);
  
          ArrayList<BluetoothGattIncludedService> includedServices =
                  new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
          for (BluetoothGattService s : mIncludedServices) {
              includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
                      s.getInstanceId(), s.getType()));
          }
          out.writeTypedList(includedServices);
      }
  
      public static final @android.annotation.NonNull Parcelable.Creator<BluetoothGattService> CREATOR =
              new Parcelable.Creator<BluetoothGattService>() {
          public BluetoothGattService createFromParcel(Parcel in) {
              return new BluetoothGattService(in);
          }
  
          public BluetoothGattService[] newArray(int size) {
              return new BluetoothGattService[size];
          }
      };
  
      private BluetoothGattService(Parcel in) {
          mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
          mInstanceId = in.readInt();
          mServiceType = in.readInt();
  
          mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
  
          ArrayList<BluetoothGattCharacteristic> chrcs =
                  in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
          if (chrcs != null) {
              for (BluetoothGattCharacteristic chrc : chrcs) {
                  chrc.setService(this);
                  mCharacteristics.add(chrc);
              }
          }
  
          mIncludedServices = new ArrayList<BluetoothGattService>();
  
          ArrayList<BluetoothGattIncludedService> inclSvcs =
                  in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
          if (chrcs != null) {
              for (BluetoothGattIncludedService isvc : inclSvcs) {
                  mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
                          isvc.getInstanceId(), isvc.getType()));
              }
          }
      }
  
      /**
       * Returns the device associated with this service.
       *
       * @hide
       */
      /*package*/ BluetoothDevice getDevice() {
          return mDevice;
      }
  
      /**
       * Returns the device associated with this service.
       *
       * @hide
       */
      /*package*/ void setDevice(BluetoothDevice device) {
          mDevice = device;
      }
  
      /**
       * Add an included service to this service.
       * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
       *
       * @param service The service to be added
       * @return true, if the included service was added to the service
       */
      public boolean addService(BluetoothGattService service) {
          mIncludedServices.add(service);
          return true;
      }
  
      /**
       * Add a characteristic to this service.
       * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
       *
       * @param characteristic The characteristics to be added
       * @return true, if the characteristic was added to the service
       */
      public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
          mCharacteristics.add(characteristic);
          characteristic.setService(this);
          return true;
      }
  
      /**
       * Get characteristic by UUID and instanceId.
       *
       * @hide
       */
      /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
          for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
              if (uuid.equals(characteristic.getUuid())
                      && characteristic.getInstanceId() == instanceId) {
                  return characteristic;
              }
          }
          return null;
      }
  
      /**
       * Force the instance ID.
       *
       * @hide
       */
      @UnsupportedAppUsage
      public void setInstanceId(int instanceId) {
          mInstanceId = instanceId;
      }
  
      /**
       * Get the handle count override (conformance testing.
       *
       * @hide
       */
      /*package*/ int getHandles() {
          return mHandles;
      }
  
      /**
       * Force the number of handles to reserve for this service.
       * This is needed for conformance testing only.
       *
       * @hide
       */
      public void setHandles(int handles) {
          mHandles = handles;
      }
  
      /**
       * Add an included service to the internal map.
       *
       * @hide
       */
      public void addIncludedService(BluetoothGattService includedService) {
          mIncludedServices.add(includedService);
      }
  
      /**
       * Returns the UUID of this service
       *
       * @return UUID of this service
       */
      public UUID getUuid() {
          return mUuid;
      }
  
      /**
       * Returns the instance ID for this service
       *
       * <p>If a remote device offers multiple services with the same UUID
       * (ex. multiple battery services for different batteries), the instance
       * ID is used to distuinguish services.
       *
       * @return Instance ID of this service
       */
      public int getInstanceId() {
          return mInstanceId;
      }
  
      /**
       * Get the type of this service (primary/secondary)
       */
      public int getType() {
          return mServiceType;
      }
  
      /**
       * Get the list of included GATT services for this service.
       *
       * @return List of included services or empty list if no included services were discovered.
       */
      public List<BluetoothGattService> getIncludedServices() {
          return mIncludedServices;
      }
  
      /**
       * Returns a list of characteristics included in this service.
       *
       * @return Characteristics included in this service
       */
      public List<BluetoothGattCharacteristic> getCharacteristics() {
          return mCharacteristics;
      }
  
      /**
       * Returns a characteristic with a given UUID out of the list of
       * characteristics offered by this service.
       *
       * <p>This is a convenience function to allow access to a given characteristic
       * without enumerating over the list returned by {@link #getCharacteristics}
       * manually.
       *
       * <p>If a remote service offers multiple characteristics with the same
       * UUID, the first instance of a characteristic with the given UUID
       * is returned.
       *
       * @return GATT characteristic object or null if no characteristic with the given UUID was
       * found.
       */
      public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
          for (BluetoothGattCharacteristic characteristic : mCharacteristics) {
              if (uuid.equals(characteristic.getUuid())) {
                  return characteristic;
              }
          }
          return null;
      }
  
      /**
       * Returns whether the uuid of the service should be advertised.
       *
       * @hide
       */
      public boolean isAdvertisePreferred() {
          return mAdvertisePreferred;
      }
  
      /**
       * Set whether the service uuid should be advertised.
       *
       * @hide
       */
      @UnsupportedAppUsage
      public void setAdvertisePreferred(boolean advertisePreferred) {
          mAdvertisePreferred = advertisePreferred;
      }
  }
  