1 /* 2 * Copyright (C) 2024 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 17 package com.android.bluetooth.pbapclient; 18 19 public class PbapApplicationParameters { 20 private static final String TAG = PbapApplicationParameters.class.getSimpleName(); 21 22 // Max size for a phonebook, which determines the max size of a batch and an offset. This comes 23 // from the fact that each field is 2 bytes -> 16 bits -> [0, 65535] (i.e, inclusive) 24 public static final int MAX_PHONEBOOK_SIZE = 65535; 25 26 // Application Parameter Header keys (PBAP 1.2.3, Section 6.2.1) 27 public static final byte OAP_ORDER = 0x01; 28 public static final byte OAP_SEARCH_VALUE = 0x02; 29 public static final byte OAP_SEARCH_PROPERTY = 0x03; 30 public static final byte OAP_MAX_LIST_COUNT = 0x04; 31 public static final byte OAP_LIST_START_OFFSET = 0x05; 32 public static final byte OAP_PROPERTY_SELECTOR = 0x06; 33 public static final byte OAP_FORMAT = 0x07; 34 public static final byte OAP_PHONEBOOK_SIZE = 0x08; 35 public static final byte OAP_NEW_MISSED_CALLS = 0x09; 36 public static final byte OAP_PRIMARY_FOLDER_VERSION = 0x0A; 37 public static final byte OAP_SECONDARY_FOLDER_VERSION = 0x0B; 38 public static final byte OAP_VCARD_SELECTOR = 0x0C; 39 public static final byte OAP_DATABASE_IDENTIFIER = 0x0D; 40 public static final byte OAP_VCARD_SELECTOR_OPERATOR = 0x0E; 41 public static final byte OAP_RESET_NEW_MISSED_CALLS = 0x0F; 42 public static final byte OAP_PBAP_SUPPORTED_FEATURES = 0x10; 43 44 // Property Selector "filter" constants, PBAP 1.2.3, section 5.1.4.1 45 public static final long PROPERTIES_ALL = 0; 46 public static final long PROPERTY_VERSION = 1 << 0; 47 public static final long PROPERTY_FN = 1 << 1; 48 public static final long PROPERTY_N = 1 << 2; 49 public static final long PROPERTY_PHOTO = 1 << 3; 50 public static final long PROPERTY_ADR = 1 << 5; 51 public static final long PROPERTY_TEL = 1 << 7; 52 public static final long PROPERTY_EMAIL = 1 << 8; 53 public static final long PROPERTY_NICKNAME = 1 << 23; 54 55 // MaxListCount field, PBAP 1.2.3, Section 5.3.4.4: "0" signifies to the PSE that the PCE is 56 // requesting the number of indexes in the phonebook of interest that are actually used 57 // (i.e. indexes that correspond to non-NULL entries). Using this causes other parameters to be 58 // ignored. Only metadata will be returned, like the size. 59 public static final int RETURN_SIZE_ONLY = 0; 60 61 private final long mProperties; // 64-bit property selector bit field, 8 bytes 62 private final byte mFormat; // Vcard format, 0 or 1, 1 byte, From PbapVcardList object 63 private final int mMaxListCount; // The total number of items to fetch, for batching, 2 bytes 64 private final int mListStartOffset; // The item index to start at, for batching, 2 bytes 65 PbapApplicationParameters(long properties, byte format, int maxListCount, int listStartOffset)66 PbapApplicationParameters(long properties, byte format, int maxListCount, int listStartOffset) { 67 if (maxListCount < 0 || maxListCount > MAX_PHONEBOOK_SIZE) { 68 throw new IllegalArgumentException("maxListCount should be [0, 65535]"); 69 } 70 if (listStartOffset < 0 || listStartOffset > MAX_PHONEBOOK_SIZE) { 71 throw new IllegalArgumentException("listStartOffset should be [0, 65535]"); 72 } 73 if (format != PbapPhonebook.FORMAT_VCARD_21 && format != PbapPhonebook.FORMAT_VCARD_30) { 74 throw new IllegalArgumentException("VCard format must be 2.1 or 3.0"); 75 } 76 77 mProperties = properties; 78 mFormat = format; 79 mMaxListCount = maxListCount; 80 mListStartOffset = listStartOffset; 81 } 82 getPropertySelectorMask()83 public long getPropertySelectorMask() { 84 return mProperties; 85 } 86 getVcardFormat()87 public byte getVcardFormat() { 88 return mFormat; 89 } 90 getMaxListCount()91 public int getMaxListCount() { 92 return mMaxListCount; 93 } 94 getListStartOffset()95 public int getListStartOffset() { 96 return mListStartOffset; 97 } 98 propertiesToString(long properties)99 public static String propertiesToString(long properties) { 100 if (properties == PROPERTIES_ALL) { 101 return "PROPERTIES_ALL"; 102 } 103 104 StringBuilder sb = new StringBuilder(); 105 sb.append("["); 106 if ((properties & PROPERTY_VERSION) != 0) { 107 sb.append("PROPERTY_VERSION "); 108 } 109 if ((properties & PROPERTY_FN) != 0) { 110 sb.append("PROPERTY_FN "); 111 } 112 if ((properties & PROPERTY_N) != 0) { 113 sb.append("PROPERTY_N "); 114 } 115 if ((properties & PROPERTY_PHOTO) != 0) { 116 sb.append("PROPERTY_PHOTO "); 117 } 118 if ((properties & PROPERTY_ADR) != 0) { 119 sb.append("PROPERTY_ADR "); 120 } 121 if ((properties & PROPERTY_TEL) != 0) { 122 sb.append("PROPERTY_TEL "); 123 } 124 if ((properties & PROPERTY_EMAIL) != 0) { 125 sb.append("PROPERTY_EMAIL "); 126 } 127 if ((properties & PROPERTY_NICKNAME) != 0) { 128 sb.append("PROPERTY_NICKNAME "); 129 } 130 sb.deleteCharAt(sb.length() - 1); 131 sb.append("]"); 132 return sb.toString(); 133 } 134 135 @Override toString()136 public String toString() { 137 return "<" 138 + TAG 139 + (" properties=" + propertiesToString(getPropertySelectorMask())) 140 + (" format=" + getVcardFormat()) 141 + (" maxListCount=" + getMaxListCount()) 142 + (" listStartOffset=" + getListStartOffset()) 143 + ">"; 144 } 145 } 146