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 55 public static boolean hasFilter(byte[] filter) { 56 return filter != null && filter.length > 0; 57 } 58 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 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 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 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 } 137 return isSet; 138 } 139 140 public static String getProfileName(Context context) { 141 Cursor c = context.getContentResolver().query( 142 Profile.CONTENT_URI, new String[] { Profile.DISPLAY_NAME}, null, 143 null, null); 144 String ownerName =null; 145 if (c!= null && c.moveToFirst()) { 146 ownerName = c.getString(0); 147 } 148 if (c != null) { 149 c.close(); 150 } 151 return ownerName; 152 } 153 public static final String createProfileVCard(Context ctx, final int vcardType,final byte[] filter) { 154 VCardComposer composer = null; 155 String vcard = null; 156 try { 157 composer = createFilteredVCardComposer(ctx, vcardType, filter); 158 if (composer 159 .init(Profile.CONTENT_URI, null, null, null, null, Uri 160 .withAppendedPath(Profile.CONTENT_URI, 161 RawContactsEntity.CONTENT_URI 162 .getLastPathSegment()))) { 163 vcard = composer.createOneEntry(); 164 } else { 165 Log.e(TAG, 166 "Unable to create profile vcard. Error initializing composer: " 167 + composer.getErrorReason()); 168 } 169 } catch (Throwable t) { 170 Log.e(TAG, "Unable to create profile vcard.", t); 171 } 172 if (composer != null) { 173 try { 174 composer.terminate(); 175 } catch (Throwable t) { 176 177 } 178 } 179 return vcard; 180 } 181 182 public static boolean createProfileVCardFile(File file, Context context) { 183 // File defaultFile = new 184 // File(OppApplicationConfig.OPP_OWNER_VCARD_PATH); 185 FileInputStream is = null; 186 FileOutputStream os = null; 187 boolean success = true; 188 try { 189 AssetFileDescriptor fd = context.getContentResolver() 190 .openAssetFileDescriptor(Profile.CONTENT_VCARD_URI, "r"); 191 192 if(fd == null) 193 { 194 return false; 195 } 196 is = fd.createInputStream(); 197 os = new FileOutputStream(file); 198 Utils.copyStream(is, os, 200); 199 } catch (Throwable t) { 200 Log.e(TAG, "Unable to create default contact vcard file", t); 201 success = false; 202 } 203 Utils.safeCloseStream(is); 204 Utils.safeCloseStream(os); 205 return success; 206 } 207 } 208