summaryrefslogtreecommitdiffstats
path: root/core/java/android/bluetooth/Database.java
blob: fef641a5f7ca0776e81d9ac152b42de1acc7bc20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Copyright (C) 2007 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.bluetooth.RfcommSocket;

import android.util.Log;

import java.io.*;
import java.util.*;

/**
 * The Android Bluetooth API is not finalized, and *will* change. Use at your
 * own risk.
 * 
 * A low-level API to the Service Discovery Protocol (SDP) Database.
 *
 * Allows service records to be added to the local SDP database. Once added,
 * these services will be advertised to remote devices when they make SDP
 * queries on this device.
 *
 * Currently this API is a thin wrapper to the bluez SDP Database API. See:
 * http://wiki.bluez.org/wiki/Database
 * http://wiki.bluez.org/wiki/HOWTO/ManagingServiceRecords
 * @hide
 */
public final class Database {
    private static Database mInstance;

    private static final String sLogName = "android.bluetooth.Database";

    /**
     * Class load time initialization
     */
    static {
        classInitNative();
    }
    private native static void classInitNative();

    /**
     * Private to enforce singleton property
     */
    private Database() {
        initializeNativeDataNative();
    }
    private native void initializeNativeDataNative();

    protected void finalize() throws Throwable {
        try {
            cleanupNativeDataNative();
        } finally {
            super.finalize();
        }
    }
    private native void cleanupNativeDataNative();

    /**
     * Singelton accessor
     * @return The singleton instance of Database
     */
    public static synchronized Database getInstance() {
        if (mInstance == null) {
            mInstance = new Database();
        }
        return mInstance;
    }

    /**
     * Advertise a service with an RfcommSocket.
     *
     * This adds the service the SDP Database with the following attributes
     * set: Service Name, Protocol Descriptor List, Service Class ID List
     * TODO: Construct a byte[] record directly, rather than via XML.
     * @param       socket The rfcomm socket to advertise (by channel).
     * @param       serviceName A short name for this service
     * @param       uuid
     *                  Unique identifier for this service, by which clients
     *                  can search for your service
     * @return      Handle to the new service record
     */
    public int advertiseRfcommService(RfcommSocket socket,
                                      String serviceName,
                                      UUID uuid) throws IOException {
        String xmlRecord =
                "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
                "<record>\n" +
                "  <attribute id=\"0x0001\">\n" + // ServiceClassIDList
                "    <sequence>\n" +
                "      <uuid value=\""
                        + uuid.toString() +       // UUID for this service
                        "\"/>\n" +
                "    </sequence>\n" +
                "  </attribute>\n" +
                "  <attribute id=\"0x0004\">\n" + // ProtocolDescriptorList
                "    <sequence>\n" +
                "      <sequence>\n" +
                "        <uuid value=\"0x0100\"/>\n" +  // L2CAP
                "      </sequence>\n" +
                "      <sequence>\n" +
                "        <uuid value=\"0x0003\"/>\n" +  // RFCOMM
                "        <uint8 value=\"" +
                        socket.getPort() +              // RFCOMM port
                        "\" name=\"channel\"/>\n" +
                "      </sequence>\n" +
                "    </sequence>\n" +
                "  </attribute>\n" +
                "  <attribute id=\"0x0100\">\n" + // ServiceName
                "    <text value=\"" + serviceName + "\"/>\n" +
                "  </attribute>\n" +
                "</record>\n";
        Log.i(sLogName, xmlRecord);
        return addServiceRecordFromXml(xmlRecord);
    }


    /**
     * Add a new service record.
     * @param record The byte[] record
     * @return       A handle to the new record
     */
    public synchronized int addServiceRecord(byte[] record) throws IOException {
        int handle = addServiceRecordNative(record);
        Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
        return handle;
    }
    private native int addServiceRecordNative(byte[] record)
            throws IOException;

    /**
     * Add a new service record, using XML.
     * @param record The record as an XML string
     * @return       A handle to the new record
     */
    public synchronized int addServiceRecordFromXml(String record) throws IOException {
        int handle = addServiceRecordFromXmlNative(record);
        Log.i(sLogName, "Added SDP record: " + Integer.toHexString(handle));
        return handle;
    }
    private native int addServiceRecordFromXmlNative(String record)
            throws IOException;

    /**
     * Update an exisiting service record.
     * @param handle Handle to exisiting record
     * @param record The updated byte[] record
     */
    public synchronized void updateServiceRecord(int handle, byte[] record) {
        try {
            updateServiceRecordNative(handle, record);
        } catch (IOException e) {
            Log.e(getClass().toString(), e.getMessage());
        }
    }
    private native void updateServiceRecordNative(int handle, byte[] record)
            throws IOException;

    /**
     * Update an exisiting record, using XML.
     * @param handle Handle to exisiting record
     * @param record The record as an XML string.
     */
    public synchronized void updateServiceRecordFromXml(int handle, String record) {
        try {
            updateServiceRecordFromXmlNative(handle, record);
        } catch (IOException e) {
            Log.e(getClass().toString(), e.getMessage());
        }
    }
    private native void updateServiceRecordFromXmlNative(int handle, String record)
            throws IOException;

    /**
     * Remove a service record.
     * It is only possible to remove service records that were added by the
     * current connection.
     * @param handle Handle to exisiting record to be removed
     */
    public synchronized void removeServiceRecord(int handle) {
        try {
            removeServiceRecordNative(handle);
        } catch (IOException e) {
            Log.e(getClass().toString(), e.getMessage());
        }
    }
    private native void removeServiceRecordNative(int handle) throws IOException;
}