• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /************************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ************************************************************************************/
18 package com.android.bluetooth.pbap;
19 
20 import android.content.Context;
21 import android.os.SystemProperties;
22 import android.util.Log;
23 
24 import com.android.bluetooth.Utils;
25 import com.android.bluetooth.pbap.BluetoothPbapService;
26 import com.android.vcard.VCardComposer;
27 import com.android.vcard.VCardConfig;
28 
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileOutputStream;
32 
33 import android.content.Context;
34 import android.content.res.AssetFileDescriptor;
35 import android.database.Cursor;
36 import android.net.Uri;
37 import android.provider.ContactsContract.Contacts;
38 import android.provider.ContactsContract.Profile;
39 import android.provider.ContactsContract.RawContactsEntity;
40 
41 
42 import com.android.vcard.VCardComposer;
43 import com.android.vcard.VCardConfig;
44 
45 
46 public class BluetoothPbapUtils {
47 
48     private static final String TAG = "FilterUtils";
49     private static final boolean V = BluetoothPbapService.VERBOSE;
50 
51     public static int FILTER_PHOTO = 3;
52     public static int FILTER_TEL = 7;
53     public static int FILTER_NICKNAME = 23;
54 
hasFilter(byte[] filter)55     public static boolean hasFilter(byte[] filter) {
56         return filter != null && filter.length > 0;
57     }
58 
isNameAndNumberOnly(byte[] filter)59     public static boolean isNameAndNumberOnly(byte[] filter) {
60         // For vcard 2.0: VERSION,N,TEL is mandatory
61         // For vcard 3.0, VERSION,N,FN,TEL is mandatory
62         // So we only need to make sure that no other fields except optionally
63         // NICKNAME is set
64 
65         // Check that an explicit filter is not set. If not, this means
66         // return everything
67         if (!hasFilter(filter)) {
68             Log.v(TAG, "No filter set. isNameAndNumberOnly=false");
69             return false;
70         }
71 
72         // Check bytes 0-4 are all 0
73         for (int i = 0; i <= 4; i++) {
74             if (filter[i] != 0) {
75                 return false;
76             }
77         }
78         // On byte 5, only BIT_NICKNAME can be set, so make sure
79         // rest of bits are not set
80         if ((filter[5] & 0x7F) > 0) {
81             return false;
82         }
83 
84         // Check byte 6 is not set
85         if (filter[6] != 0) {
86             return false;
87         }
88 
89         // Check if bit#3-6 is set. Return false if so.
90         if ((filter[7] & 0x78) > 0) {
91             return false;
92         }
93 
94         return true;
95     }
96 
isFilterBitSet(byte[] filter, int filterBit)97     public static boolean isFilterBitSet(byte[] filter, int filterBit) {
98         if (hasFilter(filter)) {
99             int byteNumber = 7 - filterBit / 8;
100             int bitNumber = filterBit % 8;
101             if (byteNumber < filter.length) {
102                 return (filter[byteNumber] & (1 << bitNumber)) > 0;
103             }
104         }
105         return false;
106     }
107 
createFilteredVCardComposer(final Context ctx, final int vcardType, final byte[] filter)108     public static VCardComposer createFilteredVCardComposer(final Context ctx,
109             final int vcardType, final byte[] filter) {
110         int vType = vcardType;
111         /*
112         boolean isNameNumberOnly = isNameAndNumberOnly(filter);
113         if (isNameNumberOnly) {
114             if (V)
115                 Log.v(TAG, "Creating Name/Number only VCardComposer...");
116             vType |= VCardConfig.FLAG_NAME_NUMBER_ONLY_EXPORT;
117         } else {
118         */
119         boolean includePhoto = BluetoothPbapConfig.includePhotosInVcard()
120                     && (!hasFilter(filter) || isFilterBitSet(filter, FILTER_PHOTO));
121         if (!includePhoto) {
122             if (V) Log.v(TAG, "Excluding images from VCardComposer...");
123             vType |= VCardConfig.FLAG_REFRAIN_IMAGE_EXPORT;
124         }
125         //}
126         return new VCardComposer(ctx, vType, true);
127     }
128 
isProfileSet(Context context)129     public static boolean isProfileSet(Context context) {
130         Cursor c = context.getContentResolver().query(
131                 Profile.CONTENT_VCARD_URI, new String[] { Profile._ID }, null,
132                 null, null);
133         boolean isSet = (c != null && c.getCount() > 0);
134         if (c != null) {
135             c.close();
136             c = null;
137         }
138         return isSet;
139     }
140 
getProfileName(Context context)141     public static String getProfileName(Context context) {
142         Cursor c = context.getContentResolver().query(
143                 Profile.CONTENT_URI, new String[] { Profile.DISPLAY_NAME}, null,
144                 null, null);
145         String ownerName =null;
146         if (c!= null && c.moveToFirst()) {
147             ownerName = c.getString(0);
148         }
149         if (c != null) {
150             c.close();
151             c = null;
152         }
153         return ownerName;
154     }
createProfileVCard(Context ctx, final int vcardType,final byte[] filter)155     public static final String createProfileVCard(Context ctx, final int vcardType,final byte[] filter) {
156         VCardComposer composer = null;
157         String vcard = null;
158         try {
159             composer = createFilteredVCardComposer(ctx, vcardType, filter);
160             if (composer
161                     .init(Profile.CONTENT_URI, null, null, null, null, Uri
162                             .withAppendedPath(Profile.CONTENT_URI,
163                                     RawContactsEntity.CONTENT_URI
164                                             .getLastPathSegment()))) {
165                 vcard = composer.createOneEntry();
166             } else {
167                 Log.e(TAG,
168                         "Unable to create profile vcard. Error initializing composer: "
169                                 + composer.getErrorReason());
170             }
171         } catch (Throwable t) {
172             Log.e(TAG, "Unable to create profile vcard.", t);
173         }
174         if (composer != null) {
175             try {
176                 composer.terminate();
177             } catch (Throwable t) {
178 
179             }
180         }
181         return vcard;
182     }
183 
createProfileVCardFile(File file, Context context)184     public static boolean createProfileVCardFile(File file, Context context) {
185         // File defaultFile = new
186         // File(OppApplicationConfig.OPP_OWNER_VCARD_PATH);
187         FileInputStream is = null;
188         FileOutputStream os = null;
189         boolean success = true;
190         try {
191             AssetFileDescriptor fd = context.getContentResolver()
192                     .openAssetFileDescriptor(Profile.CONTENT_VCARD_URI, "r");
193 
194             if(fd == null)
195             {
196                 return false;
197             }
198             is = fd.createInputStream();
199             os = new FileOutputStream(file);
200             Utils.copyStream(is, os, 200);
201         } catch (Throwable t) {
202             Log.e(TAG, "Unable to create default contact vcard file", t);
203             success = false;
204         }
205         Utils.safeCloseStream(is);
206         Utils.safeCloseStream(os);
207         return success;
208     }
209 }
210