1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.bluetooth.gatt; 17 18 import java.util.ArrayList; 19 import java.util.List; 20 import java.util.UUID; 21 22 class ServiceDeclaration { 23 private static final boolean DBG = GattServiceConfig.DBG; 24 private static final String TAG = GattServiceConfig.TAG_PREFIX + "ServiceDeclaration"; 25 26 public static final byte TYPE_UNDEFINED = 0; 27 public static final byte TYPE_SERVICE = 1; 28 public static final byte TYPE_CHARACTERISTIC = 2; 29 public static final byte TYPE_DESCRIPTOR = 3; 30 public static final byte TYPE_INCLUDED_SERVICE = 4; 31 32 class Entry { 33 byte type = TYPE_UNDEFINED; 34 UUID uuid = null; 35 int instance = 0; 36 int permissions = 0; 37 int properties = 0; 38 int serviceType = 0; 39 int serviceHandle = 0; 40 boolean advertisePreferred = false; 41 42 Entry(UUID uuid, int serviceType, int instance) { 43 this.type = TYPE_SERVICE; 44 this.uuid = uuid; 45 this.instance = instance; 46 this.serviceType = serviceType; 47 } 48 49 Entry(UUID uuid, int serviceType, int instance, boolean advertisePreferred) { 50 this.type = TYPE_SERVICE; 51 this.uuid = uuid; 52 this.instance = instance; 53 this.serviceType = serviceType; 54 this.advertisePreferred = advertisePreferred; 55 } 56 57 Entry(UUID uuid, int properties, int permissions, int instance) { 58 this.type = TYPE_CHARACTERISTIC; 59 this.uuid = uuid; 60 this.instance = instance; 61 this.permissions = permissions; 62 this.properties = properties; 63 } 64 65 Entry(UUID uuid, int permissions) { 66 this.type = TYPE_DESCRIPTOR; 67 this.uuid = uuid; 68 this.permissions = permissions; 69 } 70 } 71 72 // guards access to mEntries and mNumHandles in order to make this class thread-safe 73 private final Object mLock = new Object(); 74 private final List<Entry> mEntries = new ArrayList<>(); 75 private int mNumHandles = 0; 76 77 void addService(UUID uuid, int serviceType, int instance, int minHandles, 78 boolean advertisePreferred) { 79 synchronized (mLock) { 80 mEntries.add(new Entry(uuid, serviceType, instance, advertisePreferred)); 81 if (minHandles == 0) { 82 ++mNumHandles; 83 } else { 84 mNumHandles = minHandles; 85 } 86 } 87 } 88 89 void addIncludedService(UUID uuid, int serviceType, int instance) { 90 Entry entry = new Entry(uuid, serviceType, instance); 91 entry.type = TYPE_INCLUDED_SERVICE; 92 synchronized (mLock) { 93 mEntries.add(entry); 94 ++mNumHandles; 95 } 96 } 97 98 void addCharacteristic(UUID uuid, int properties, int permissions) { 99 synchronized (mLock) { 100 mEntries.add(new Entry(uuid, properties, permissions, 0 /*instance*/)); 101 mNumHandles += 2; 102 } 103 } 104 105 void addDescriptor(UUID uuid, int permissions) { 106 synchronized (mLock) { 107 mEntries.add(new Entry(uuid, permissions)); 108 ++mNumHandles; 109 } 110 } 111 112 Entry getNext() { 113 synchronized (mLock) { 114 if (mEntries.isEmpty()) return null; 115 Entry entry = mEntries.get(0); 116 mEntries.remove(0); 117 return entry; 118 } 119 } 120 121 boolean isServiceAdvertisePreferred(UUID uuid) { 122 synchronized (mLock) { 123 for (Entry entry : mEntries) { 124 if (entry.uuid.equals(uuid)) { 125 return entry.advertisePreferred; 126 } 127 } 128 return false; 129 } 130 } 131 132 int getNumHandles() { 133 synchronized (mLock) { 134 return mNumHandles; 135 } 136 } 137 } 138