1bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde/*
2bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* Copyright (C) 2015 Samsung System LSI
3bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* Licensed under the Apache License, Version 2.0 (the "License");
4bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* you may not use this file except in compliance with the License.
5bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* You may obtain a copy of the License at
6bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde*
7bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde*      http://www.apache.org/licenses/LICENSE-2.0
8bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde*
9bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* Unless required by applicable law or agreed to in writing, software
10bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* distributed under the License is distributed on an "AS IS" BASIS,
11bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* See the License for the specific language governing permissions and
13bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde* limitations under the License.
14bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde*/
15bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondepackage com.android.bluetooth.sdp;
16bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
17bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.BluetoothDevice;
18bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpMasRecord;
19bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpMnsRecord;
20bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpOppOpsRecord;
21bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpPseRecord;
221f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bondeimport android.bluetooth.SdpSapsRecord;
23bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.bluetooth.SdpRecord;
24bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.content.Intent;
25bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.os.Handler;
26bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.os.Message;
27bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.os.ParcelUuid;
28bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.os.Parcelable;
29bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.util.Log;
30bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
31bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.Utils;
32bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.btservice.AbstractionLayer;
33bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport com.android.bluetooth.btservice.AdapterService;
34bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
35bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.ArrayList;
36bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.util.Arrays;
37bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
38bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondepublic class SdpManager {
39bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
40bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final boolean D = true;
41bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final boolean V = false;
42bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final String TAG="SdpManager";
43bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
44bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    // TODO: When changing PBAP to use this new API.
45bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    //       Move the defines to the profile (PBAP already have the feature bits)
46bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* PBAP repositories */
47bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte PBAP_REPO_LOCAL        = 0x01<<0;
48bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte PBAP_REPO_SIM          = 0x01<<1;
49bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte PBAP_REPO_SPEED_DAIL   = 0x01<<2;
50bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte PBAP_REPO_FAVORITES    = 0x01<<3;
51bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
52bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    // TODO: When changing OPP to use this new API.
53bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    //       Move the defines to the profile
54bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* Object Push formats */
55bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_VCARD21     = 0x01;
56bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_VCARD30     = 0x02;
57bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_VCAL10      = 0x03;
58bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_ICAL20      = 0x04;
59bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_VNOTE       = 0x05;
60bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_VMESSAGE    = 0x06;
61bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte OPP_FORMAT_ANY_TYPE_OF_OBJ = (byte)0xFF;
62bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
63bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static final byte[] OPP_FORMAT_ALL= {
64bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_VCARD21,
65bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_VCARD30,
66bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_VCAL10,
67bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_ICAL20,
68bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_VNOTE,
69bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_VMESSAGE,
70bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        OPP_FORMAT_ANY_TYPE_OF_OBJ};
71bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
72bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* Variables to keep track of ongoing and queued search requests.
73bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * mTrackerLock must be held, when using/changing sSdpSearchTracker
74bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * and mSearchInProgress. */
75bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    static SdpSearchTracker sSdpSearchTracker;
76bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    static boolean mSearchInProgress = false;
77bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    static Object mTrackerLock = new Object();
78bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
79bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* The timeout to wait for reply from native. Should never fire. */
80bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final int SDP_INTENT_DELAY = 6000;
81bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final int MESSAGE_SDP_INTENT = 2;
82bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
83bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    // We need a reference to the adapter service, to be able to send intents
84bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static AdapterService sAdapterService;
85bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static boolean sNativeAvailable;
86bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
87bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    // This object is a singleton
88bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static SdpManager sSdpManager = null;
89bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
90bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    static {
91bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        classInitNative();
92bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
93bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
94bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native static void classInitNative();
95bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native void initializeNative();
96bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native void cleanupNative();
97bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native boolean sdpSearchNative(byte[] address, byte[] uuid);
98bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
99bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native int sdpCreateMapMasRecordNative(String serviceName, int masId,
100bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommChannel, int l2capPsm, int version, int msgTypes, int features);
101bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
102bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native int sdpCreateMapMnsRecordNative(String serviceName,
103bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommChannel, int l2capPsm, int version, int features);
104bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
105bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native int sdpCreatePbapPseRecordNative(String serviceName, int rfcommChannel,
106bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int l2capPsm, int version, int repositories, int features);
107bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
108bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native int sdpCreateOppOpsRecordNative(String serviceName,
109bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommChannel, int l2capPsm, int version, byte[] formats_list);
110bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
1111f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    private native int sdpCreateSapsRecordNative(String serviceName, int rfcommChannel,
1121f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            int version);
1131f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde
114bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private native boolean sdpRemoveSdpRecordNative(int record_id);
115bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
116bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
117bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* Inner class used for wrapping sdp search instance data */
118bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private class SdpSearchInstance {
119bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        private final BluetoothDevice mDevice;
120bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        private final ParcelUuid mUuid;
121bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        private int mStatus = 0;
122bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        private boolean mSearching;
123bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        /* TODO: If we change the API to use another mechanism than intents for
124bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         *       delivering the results, this would be the place to keep a list
125bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         *       of the objects to deliver the results to. */
126bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public SdpSearchInstance(int status, BluetoothDevice device, ParcelUuid uuid){
127bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            this.mDevice = device;
128bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            this.mUuid = uuid;
129bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            this.mStatus = status;
130bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSearching = true;
131bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
132bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public BluetoothDevice getDevice() {
133bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return mDevice;
134bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
135bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public ParcelUuid getUuid() {
136bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return mUuid;
137bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
138bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public int getStatus(){
139bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return mStatus;
140bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
141bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
142bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public void setStatus(int status) {
143bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            this.mStatus = status;
144bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
145bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
146bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public void startSearch() {
147bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSearching = true;
148bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Message message = mHandler.obtainMessage(MESSAGE_SDP_INTENT, this);
149bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mHandler.sendMessageDelayed(message, SDP_INTENT_DELAY);
150bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
151bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
152bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public void stopSearch() {
153bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(mSearching) {
154bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                mHandler.removeMessages(MESSAGE_SDP_INTENT, this);
155bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
156bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSearching = false;
157bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
158bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public boolean isSearching() {
159bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return mSearching;
160bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
161bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
162bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
163bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
164bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* We wrap the ArrayList class to decorate with functionality to
165bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * find an instance based on UUID AND device address.
166bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * As we use a mix of byte[] and object instances, this is more
167bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * efficient than implementing comparable. */
168bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    class SdpSearchTracker {
169bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        private final ArrayList<SdpSearchInstance> list = new ArrayList<SdpSearchInstance>();
170bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
171bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        void clear() {
172bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            list.clear();
173bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
174bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
175bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        boolean add(SdpSearchInstance inst){
176bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return list.add(inst);
177bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
178bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
179bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        boolean remove(SdpSearchInstance inst) {
180bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return list.remove(inst);
181bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
182bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
183bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        SdpSearchInstance getNext() {
184bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(list.size() > 0) {
185bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return list.get(0);
186bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
187bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return null;
188bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
189bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
190bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        SdpSearchInstance getSearchInstance(byte[] address, byte[] uuidBytes) {
191bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String addressString = Utils.getAddressStringFromByte(address);
192bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            ParcelUuid uuid = Utils.byteArrayToUuid(uuidBytes)[0];
193bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            for (SdpSearchInstance inst : list) {
194bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if (inst.getDevice().getAddress().equals(addressString)
195bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        && inst.getUuid().equals(uuid)) {
196bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    return inst;
197bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
198bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
199bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return null;
200bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
201bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
202bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        boolean isSearching(BluetoothDevice device, ParcelUuid uuid) {
203bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String addressString = device.getAddress();
204bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            for (SdpSearchInstance inst : list) {
205bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if (inst.getDevice().getAddress().equals(addressString)
206bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        && inst.getUuid().equals(uuid)) {
207bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    return inst.isSearching();
208bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
209bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
210bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return false;
211bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
212bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
213bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
214bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
215bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private SdpManager(AdapterService adapterService) {
216bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sSdpSearchTracker = new SdpSearchTracker();
217bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
218bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        /* This is only needed until intents are no longer used */
219bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sAdapterService = adapterService;
220bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        initializeNative();
221bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sNativeAvailable=true;
222bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
223bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
224bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
225bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static SdpManager init(AdapterService adapterService) {
226bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sSdpManager = new SdpManager(adapterService);
227bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sSdpManager;
228bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
229bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
230bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public static SdpManager getDefaultManager() {
231bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sSdpManager;
232bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
233bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
234bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public void cleanup() {
235bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (sSdpSearchTracker !=null) {
236bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            synchronized(mTrackerLock) {
237bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sSdpSearchTracker.clear();
238bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
239bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
240bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
241bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (sNativeAvailable) {
242bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            cleanupNative();
243bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sNativeAvailable=false;
244bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
245bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sSdpManager = null;
246bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
247bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
248bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
249bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    void sdpMasRecordFoundCallback(int status, byte[] address, byte[] uuid,
250bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int masInstanceId,
251bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int l2capPsm,
252bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommCannelNumber,
253bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int profileVersion,
254bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int supportedFeatures,
255bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int supportedMessageTypes,
256bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String serviceName,
257bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            boolean moreResults) {
258bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
259bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized(mTrackerLock) {
260bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
261bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpMasRecord sdpRecord = null;
262bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (inst == null) {
263bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.e(TAG, "sdpRecordFoundCallback: Search instance is NULL");
264bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
265bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
266bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.setStatus(status);
267bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(status == AbstractionLayer.BT_STATUS_SUCCESS) {
268bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sdpRecord = new SdpMasRecord(masInstanceId,
269bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             l2capPsm,
270bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             rfcommCannelNumber,
271bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             profileVersion,
272bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             supportedFeatures,
273bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             supportedMessageTypes,
274bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             serviceName);
275bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
276bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
277bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
278bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sendSdpIntent(inst, sdpRecord, moreResults);
279bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
280bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
281bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
282bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    void sdpMnsRecordFoundCallback(int status, byte[] address, byte[] uuid,
283bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int l2capPsm,
284bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommCannelNumber,
285bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int profileVersion,
286bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int supportedFeatures,
287bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String serviceName,
288bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            boolean moreResults) {
289bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized(mTrackerLock) {
290bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
291bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
292bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpMnsRecord sdpRecord = null;
293bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (inst == null) {
294bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.e(TAG, "sdpRecordFoundCallback: Search instance is NULL");
295bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
296bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
297bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.setStatus(status);
298bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(status == AbstractionLayer.BT_STATUS_SUCCESS) {
299bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sdpRecord = new SdpMnsRecord(l2capPsm,
300bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             rfcommCannelNumber,
301bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             profileVersion,
302bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             supportedFeatures,
303bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             serviceName);
304bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
305bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
306bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
307bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sendSdpIntent(inst, sdpRecord, moreResults);
308bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
309bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
310bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
311bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    void sdpPseRecordFoundCallback(int status, byte[] address, byte[] uuid,
312bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        int l2capPsm,
313bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        int rfcommCannelNumber,
314bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        int profileVersion,
315bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        int supportedFeatures,
316bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        int supportedRepositories,
317bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        String serviceName,
318bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                        boolean moreResults) {
319bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized(mTrackerLock) {
320bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
321bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpPseRecord sdpRecord = null;
322bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (inst == null) {
323bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.e(TAG, "sdpRecordFoundCallback: Search instance is NULL");
324bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
325bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
326bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.setStatus(status);
327bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(status == AbstractionLayer.BT_STATUS_SUCCESS) {
328bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sdpRecord = new SdpPseRecord(l2capPsm,
329bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             rfcommCannelNumber,
330bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             profileVersion,
331bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             supportedFeatures,
332bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             supportedRepositories,
333bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                             serviceName);
334bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
335bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
336bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
337bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sendSdpIntent(inst, sdpRecord, moreResults);
338bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
339bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
340bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
341bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    void sdpOppOpsRecordFoundCallback(int status, byte[] address, byte[] uuid,
342bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int l2capPsm,
343bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommCannelNumber,
344bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int profileVersion,
345bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String serviceName,
346bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            byte[] formatsList,
347bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            boolean moreResults) {
348bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
349bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized(mTrackerLock) {
350bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
351bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpOppOpsRecord sdpRecord = null;
352bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
353bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (inst == null) {
354bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.e(TAG, "sdpOppOpsRecordFoundCallback: Search instance is NULL");
355bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
356bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
357bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.setStatus(status);
358bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(status == AbstractionLayer.BT_STATUS_SUCCESS) {
359bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sdpRecord = new SdpOppOpsRecord(serviceName,
360bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                                rfcommCannelNumber,
361bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                                l2capPsm,
362bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                                profileVersion,
363bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                                formatsList);
364bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
365bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
366bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
367bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sendSdpIntent(inst, sdpRecord, moreResults);
368bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
369bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
370bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
3711f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    void sdpSapsRecordFoundCallback(int status, byte[] address, byte[] uuid,
3721f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            int rfcommCannelNumber,
3731f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            int profileVersion,
3741f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            String serviceName,
3751f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            boolean moreResults) {
3761f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde
3771f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde        synchronized(mTrackerLock) {
3781f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
3791f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            SdpSapsRecord sdpRecord = null;
3801f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            if (inst == null) {
3811f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde                Log.e(TAG, "sdpSapsRecordFoundCallback: Search instance is NULL");
3821f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde                return;
3831f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            }
3841f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            inst.setStatus(status);
3851f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            if (status == AbstractionLayer.BT_STATUS_SUCCESS) {
3861f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde                sdpRecord = new SdpSapsRecord(rfcommCannelNumber,
3871f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde                                             profileVersion,
3881f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde                                             serviceName);
3891f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            }
3901f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            if (D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
3911f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            if (D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
3921f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            sendSdpIntent(inst, sdpRecord, moreResults);
3931f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde        }
3941f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    }
3951f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde
396bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* TODO: Test or remove! */
397bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    void sdpRecordFoundCallback(int status, byte[] address, byte[] uuid,
398bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int size_record, byte[] record) {
399bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized(mTrackerLock) {
400bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
401bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = sSdpSearchTracker.getSearchInstance(address, uuid);
402bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpRecord sdpRecord = null;
403bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (inst == null) {
404bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.e(TAG, "sdpRecordFoundCallback: Search instance is NULL");
405bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
406bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
407bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.setStatus(status);
408bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(status == AbstractionLayer.BT_STATUS_SUCCESS) {
409bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if(D) Log.d(TAG, "sdpRecordFoundCallback: found a sdp record of size "
410bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        + size_record );
411bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if(D) Log.d(TAG, "Record:"+ Arrays.toString(record));
412bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                sdpRecord = new SdpRecord(size_record, record);
413bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
414bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID: " + Arrays.toString(uuid));
415bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "UUID in parcel: " + ((Utils.byteArrayToUuid(uuid))[0]).toString());
416bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sendSdpIntent(inst, sdpRecord, false);
417bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
418bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
419bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
420bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public void sdpSearch(BluetoothDevice device, ParcelUuid uuid) {
421bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (sNativeAvailable == false) {
422bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Log.e(TAG, "Native not initialized!");
423bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return;
424bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
425bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        synchronized (mTrackerLock) {
426bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if (sSdpSearchTracker.isSearching(device, uuid)) {
427bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                /* Search already in progress */
428bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                return;
429bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
430bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
431bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            SdpSearchInstance inst = new SdpSearchInstance(0, device, uuid);
432bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sSdpSearchTracker.add(inst); // Queue the request
433bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
434bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            startSearch(); // Start search if not busy
435bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
436bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
437bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
438bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
439bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* Caller must hold the mTrackerLock */
440bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private void startSearch() {
441bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
442bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        SdpSearchInstance inst = sSdpSearchTracker.getNext();
443bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
444bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if((inst != null) && (mSearchInProgress == false)) {
445bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "Starting search for UUID: "+ inst.getUuid());
446bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSearchInProgress = true;
447bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
448bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            inst.startSearch(); // Trigger timeout message
449bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
450bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sdpSearchNative(Utils.getBytesFromAddress(inst.getDevice().getAddress()),
451bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                            Utils.uuidToByteArray(inst.getUuid()));
452bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        } // Else queue is empty.
453bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        else {
454bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(D) Log.d(TAG, "startSearch(): nextInst = " + inst +
455bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    " mSearchInProgress = " + mSearchInProgress
456bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    + " - search busy or queue empty.");
457bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
458bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
459bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
460bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /* Caller must hold the mTrackerLock */
461bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private void sendSdpIntent(SdpSearchInstance inst,
462bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Parcelable record, boolean moreResults) {
463bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
464bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        inst.stopSearch();
465bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
466bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        Intent intent = new Intent(BluetoothDevice.ACTION_SDP_RECORD);
467bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
468bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, inst.getDevice());
469bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        intent.putExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, inst.getStatus());
470bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (record != null)  intent.putExtra(BluetoothDevice.EXTRA_SDP_RECORD, record);
471bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        intent.putExtra(BluetoothDevice.EXTRA_UUID, inst.getUuid());
472bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        /* TODO:  BLUETOOTH_ADMIN_PERM was private... change to callback interface.
473bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         * Keep in mind that the MAP client needs to use this as well,
474bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         * hence to make it call-backs, the MAP client profile needs to be
475bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         * part of the Bluetooth APK. */
476bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        sAdapterService.sendBroadcast(intent, AdapterService.BLUETOOTH_ADMIN_PERM);
477bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
478bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(moreResults == false) {
479bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            //Remove the outstanding UUID request
480bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            sSdpSearchTracker.remove(inst);
481bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mSearchInProgress = false;
482bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            startSearch();
483bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
484bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
485bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
486bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private final Handler mHandler = new Handler() {
487bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        @Override
488bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        public void handleMessage(Message msg) {
489bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            switch (msg.what) {
490bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            case MESSAGE_SDP_INTENT:
491bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                SdpSearchInstance msgObj = (SdpSearchInstance)msg.obj;
492bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                Log.w(TAG, "Search timedout for UUID " + msgObj.getUuid());
493bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                synchronized (mTrackerLock) {
494bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    sendSdpIntent(msgObj, null, false);
495bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
496bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                break;
497bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
498bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
499bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    };
500bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
501bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
502bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create a server side Message Access Profile Service Record.
503bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create the record once, and reuse it for all connections.
504bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * If changes to a record is needed remove the old record using {@link removeSdpRecord}
505bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * and then create a new one.
506bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param serviceName   The textual name of the service
507bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param masId         The MAS ID to associate with this SDP record
508bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param rfcommChannel The RFCOMM channel that clients can connect to
509bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
510bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param l2capPsm      The L2CAP PSM channel that clients can connect to
511bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
512bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      Supply -1 to omit the L2CAP PSM from the record.
513bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param version       The Profile version number (As specified in the Bluetooth
514bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      MAP specification)
515bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param msgTypes      The supported message types bit mask (As specified in
516bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      the Bluetooth MAP specification)
517bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param features      The feature bit mask (As specified in the Bluetooth
518bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                       MAP specification)
519bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @return a handle to the record created. The record can be removed again
520bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          using {@link removeSdpRecord}(). The record is not linked to the
521bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          creation/destruction of BluetoothSockets, hence SDP record cleanup
522bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          is a separate process.
523bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
524bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public int createMapMasRecord(String serviceName, int masId,
525bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int rfcommChannel, int l2capPsm, int version,
526bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int msgTypes, int features) {
527bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(sNativeAvailable == false) {
528bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
529bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
530bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sdpCreateMapMasRecordNative(serviceName, masId, rfcommChannel,
531bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                l2capPsm, version, msgTypes, features);
532bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
533bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
534bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
535bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create a client side Message Access Profile Service Record.
536bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create the record once, and reuse it for all connections.
537bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * If changes to a record is needed remove the old record using {@link removeSdpRecord}
538bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * and then create a new one.
539bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param serviceName   The textual name of the service
540bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param rfcommChannel The RFCOMM channel that clients can connect to
541bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
542bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param l2capPsm      The L2CAP PSM channel that clients can connect to
543bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
544bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      Supply -1 to omit the L2CAP PSM from the record.
545bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param version       The Profile version number (As specified in the Bluetooth
546bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      MAP specification)
547bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param features      The feature bit mask (As specified in the Bluetooth
548bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                       MAP specification)
549bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @return a handle to the record created. The record can be removed again
550bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          using {@link removeSdpRecord}(). The record is not linked to the
551bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          creation/destruction of BluetoothSockets, hence SDP record cleanup
552bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          is a separate process.
553bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
554bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public int createMapMnsRecord(String serviceName, int rfcommChannel,
555bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            int l2capPsm, int version, int features) {
556bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(sNativeAvailable == false) {
557bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
558bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
559bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sdpCreateMapMnsRecordNative(serviceName, rfcommChannel,
560bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                l2capPsm, version, features);
561bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
562bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
563bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
564bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create a Server side Phone Book Access Profile Service Record.
565bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create the record once, and reuse it for all connections.
566bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * If changes to a record is needed remove the old record using {@link removeSdpRecord}
567bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * and then create a new one.
568bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param serviceName   The textual name of the service
569bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param rfcommChannel The RFCOMM channel that clients can connect to
570bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
571bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param l2capPsm      The L2CAP PSM channel that clients can connect to
572bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
573bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      Supply -1 to omit the L2CAP PSM from the record.
574bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param version       The Profile version number (As specified in the Bluetooth
575bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      PBAP specification)
576bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param repositories  The supported repositories bit mask (As specified in
577bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      the Bluetooth PBAP specification)
578bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param features      The feature bit mask (As specified in the Bluetooth
579bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      PBAP specification)
580bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @return a handle to the record created. The record can be removed again
581bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          using {@link removeSdpRecord}(). The record is not linked to the
582bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          creation/destruction of BluetoothSockets, hence SDP record cleanup
583bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          is a separate process.
584bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
585bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public int createPbapPseRecord(String serviceName, int rfcommChannel, int l2capPsm,
586bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                   int version, int repositories, int features) {
587bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(sNativeAvailable == false) {
588bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
589bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
590bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sdpCreatePbapPseRecordNative(serviceName, rfcommChannel,
591bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                l2capPsm, version, repositories, features);
592bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
593bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
594bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
595bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create a Server side Object Push Profile Service Record.
596bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Create the record once, and reuse it for all connections.
597bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * If changes to a record is needed remove the old record using {@link removeSdpRecord}
598bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * and then create a new one.
599bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param serviceName   The textual name of the service
600bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param rfcommChannel The RFCOMM channel that clients can connect to
601bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
602bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param l2capPsm      The L2CAP PSM channel that clients can connect to
603bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      (obtain from BluetoothServerSocket)
604bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      Supply -1 to omit the L2CAP PSM from the record.
605bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param version       The Profile version number (As specified in the Bluetooth
606bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      OPP specification)
607bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param formatsList  A list of the supported formats (As specified in
608bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *                      the Bluetooth OPP specification)
609bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @return a handle to the record created. The record can be removed again
610bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          using {@link removeSdpRecord}(). The record is not linked to the
611bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          creation/destruction of BluetoothSockets, hence SDP record cleanup
612bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *          is a separate process.
613bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
614bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public int createOppOpsRecord(String serviceName, int rfcommChannel, int l2capPsm,
615bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                                  int version, byte[] formatsList) {
616bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(sNativeAvailable == false) {
617bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
618bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
619bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sdpCreateOppOpsRecordNative(serviceName, rfcommChannel,
620bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                 l2capPsm, version, formatsList);
621bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
622bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
6231f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    /**
6241f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * Create a server side Sim Access Profile Service Record.
6251f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * Create the record once, and reuse it for all connections.
6261f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * If changes to a record is needed remove the old record using {@link removeSdpRecord}
6271f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * and then create a new one.
6281f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * @param serviceName   The textual name of the service
6291f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * @param rfcommChannel The RFCOMM channel that clients can connect to
6301f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     *                      (obtain from BluetoothServerSocket)
6311f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * @param version       The Profile version number (As specified in the Bluetooth
6321f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     *                      SAP specification)
6331f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     * @return a handle to the record created. The record can be removed again
6341f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     *          using {@link removeSdpRecord}(). The record is not linked to the
6351f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     *          creation/destruction of BluetoothSockets, hence SDP record cleanup
6361f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     *          is a separate process.
6371f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde     */
6381f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    public int createSapsRecord(String serviceName, int rfcommChannel, int version) {
6391f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde        if (sNativeAvailable == false) {
6401f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
6411f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde        }
6421f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde        return sdpCreateSapsRecordNative(serviceName, rfcommChannel, version);
6431f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde    }
6441f1103e93ba7ebd48c57c9627dc7b262c6f01c77Casper Bonde
645bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     /**
646bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      * Remove a SDP record.
647bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      * When Bluetooth is disabled all records will be deleted, hence there
648bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      * is no need to call this function when bluetooth is disabled.
649bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      * @param recordId The Id returned by on of the createXxxXxxRecord() functions.
650bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      * @return TRUE if the record removal was initiated successfully. FALSE if the record
651bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      *         handle is not known/have already been removed.
652bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde      */
653bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public boolean removeSdpRecord(int recordId){
654bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(sNativeAvailable == false) {
655bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            throw new RuntimeException(TAG + " sNativeAvailable == false - native not initialized");
656bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
657bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return sdpRemoveSdpRecordNative(recordId);
658bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
659bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde}
660