diff options
author | Andre Eisenbach <eisenbach@google.com> | 2015-01-07 14:25:19 -0800 |
---|---|---|
committer | Andre Eisenbach <eisenbach@google.com> | 2015-01-12 13:41:06 -0800 |
commit | 5f659853fff6a50fd12e1f7956997cbef244f798 (patch) | |
tree | 5c6f446b6a2d1665a5525699e8c86882cb499e92 /src | |
parent | cd1091ef948a708bd5ce83f6dc2921710a217684 (diff) | |
download | android_packages_apps_Bluetooth-5f659853fff6a50fd12e1f7956997cbef244f798.tar.gz android_packages_apps_Bluetooth-5f659853fff6a50fd12e1f7956997cbef244f798.tar.bz2 android_packages_apps_Bluetooth-5f659853fff6a50fd12e1f7956997cbef244f798.zip |
Improve VCARD filter logic and reduce log spam
Remove a stray log message in VCardFilter.applyFilter() function that
leads to high-frequency log spam during phone book synchronization. Also
refactored the logic to avoid multiple loops & loop iterations causing
higher CPU load.
Bug: 18913091
Change-Id: I3c6d3c3373d4a74a930d182ee2641959461b0556
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java | 364 |
1 files changed, 77 insertions, 287 deletions
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java index 2c0bb4a23..d3e116e3f 100644 --- a/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java +++ b/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java @@ -520,10 +520,8 @@ public class BluetoothPbapVcardManager { if (isContacts) { VCardComposer composer = null; - FilterVcard vcardfilter= new FilterVcard(); - if (!ignorefilter) { - vcardfilter.setFilter(filter); - } + VCardFilter vcardfilter= new VCardFilter(ignorefilter ? null : filter); + HandlerForStringBuffer buffer = null; try { // Currently only support Generic Vcard 2.1 and 3.0 @@ -575,15 +573,11 @@ public class BluetoothPbapVcardManager { return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; } if (V) Log.v (TAG , "vCard from composer: " + vcard); - if (!ignorefilter) { - vcard = vcardfilter.applyFilter(vcard, vcardType21); - if (V) Log.v (TAG , "vCard on applying filter: " + vcard); - } + + vcard = vcardfilter.apply(vcard, vcardType21); vcard = StripTelephoneNumber(vcard); - if (V) { - Log.v(TAG, "Vcard Entry:"); - Log.v(TAG,vcard); - } + + if (V) Log.v (TAG, "vCard after cleanup: " + vcard); if (!buffer.onEntryCreated(vcard)) { // onEntryCreate() already emits error. @@ -724,288 +718,84 @@ public class BluetoothPbapVcardManager { } } - public class FilterVcard{ - - public FilterVcard(){ - }; - - private final int FN_BIT = 1; - - private boolean fn = true; - - private final int PHOTO_BIT = 3; - - private boolean photo = true; - - //BDAY falls under events - private final int BDAY_BIT = 4; - - private boolean bday = true; - - private final int ADR_BIT = 5; - - private boolean adr = true; - - private final int EMAIL_BIT = 8; - - private boolean email = true; - - private final int TITLE_BIT = 12; - - private boolean title = true; - - private final int ORG_BIT = 16; - - private boolean org = true; - - private final int NOTES_BIT = 17; - - private boolean notes = true; - - private final int URL_BIT = 20; - - private boolean url = true; - - private final int NICKNAME_BIT = 23; - - private boolean nickname = true; - - public void setFilter(byte[] filter){ - - fn = checkbit(FN_BIT, filter); - photo = checkbit(PHOTO_BIT, filter); - bday = checkbit(BDAY_BIT, filter); - adr = checkbit(ADR_BIT, filter); - email = checkbit(EMAIL_BIT, filter); - title = checkbit(TITLE_BIT, filter); - org = checkbit(ORG_BIT, filter); - notes = checkbit(NOTES_BIT, filter); - url = checkbit(URL_BIT, filter); - nickname = checkbit(NICKNAME_BIT, filter); - } - - private boolean checkbit (int attr_bit, byte[] filter){ - int filterlen = filter.length; - if( ((filter[filterlen -1 -((int)attr_bit/8)] >> (attr_bit%8)) & 0x01) == 0) { - return false; - } - return true; - } - - public boolean isPhotoEnabled(){ - return photo; - } - - private boolean checkValidFilter (String attr) { - if((attr.startsWith("N:")) || (attr.startsWith("TEL")) - || (attr.startsWith("VERSION")) || (attr.startsWith("URL")) - || (attr.startsWith("FN")) || (attr.startsWith("BDAY")) - || (attr.startsWith("ADR")) || (attr.startsWith("EMAIL")) - || (attr.startsWith("TITLE")) || (attr.startsWith("ORG")) - || (attr.startsWith("NOTE")) || (attr.startsWith("NICKNAME"))) { - return true; - } - return false; - } - - public String applyFilter ( String vCard, boolean vCardType21){ - String attr [] = vCard.split(System.getProperty("line.separator")); - String filteredVcard = ""; - - //FN is not the mandatory field in 2.1 vCard - if(((!fn) && (vCardType21)) && (vCard.contains("FN"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("FN")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - //NOTE: No need to check photo, we already refrained it if it is not set in the filter - if((!bday) && (vCard.contains("BDAY"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("BDAY")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!adr) && (vCard.contains("ADR"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("ADR")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!email) && (vCard.contains("EMAIL"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("EMAIL")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!title) && (vCard.contains("TITLE"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("TITLE")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!org) && (vCard.contains("ORG"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("ORG")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!notes) && (vCard.contains("NOTE"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("NOTE")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - /*Nickname is not supported in 2.1 version. - *Android still ads it for 2.1 with nickname mentioned in lower case, and therefore - *we need to check for both cases. - */ - if(((!nickname) || (vCardType21)) && (vCard.contains("NICKNAME"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("NICKNAME")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } - } - } - } - } - - if((!url) && (vCard.contains("URL"))) { - for (int i=0; i < attr.length; i++) { - if(attr[i].startsWith("URL")){ - attr[i] = ""; - /** Remove multiline Content, if any */ - /** End traversal before END:VCARD */ - for (int j = i+1; j < attr.length - 1; j++) { - if (checkValidFilter(attr[j])) { - break; - } else { - /** Continuation of above attribute, remove */ - attr[j] = ""; - } + public static class VCardFilter { + private static enum FilterBit { + // bit property onlyCheckV21 excludeForV21 + FN ( 1, "FN", true, false), + PHOTO( 3, "PHOTO", false, false), + BDAY( 4, "BDAY", false, false), + ADR( 5, "ADR", false, false), + EMAIL( 8, "EMAIL", false, false), + TITLE( 12, "TITLE", false, false), + ORG( 16, "ORG", false, false), + NOTES( 17, "NOTES", false, false), + URL( 20, "URL", false, false), + NICKNAME( 23, "NICKNAME", false, true); + + public final int pos; + public final String prop; + public final boolean onlyCheckV21; + public final boolean excludeForV21; + + FilterBit(int pos, String prop, boolean onlyCheckV21, boolean excludeForV21) { + this.pos = pos; + this.prop = prop; + this.onlyCheckV21 = onlyCheckV21; + this.excludeForV21 = excludeForV21; + } + } + + private static final String SEPARATOR = System.getProperty("line.separator"); + private final byte[] filter; + + private boolean isFilteredOut(FilterBit bit, boolean vCardType21) { + final int offset = (bit.pos / 8) + 1; + final int bit_pos = bit.pos % 8; + if (!vCardType21 && bit.onlyCheckV21) return false; + if (vCardType21 && bit.excludeForV21) return true; + if (filter == null || offset >= filter.length) return false; + return ((filter[filter.length - offset] >> bit_pos) & 0x01) != 0; + } + + VCardFilter(byte[] filter) { + this.filter = filter; + } + + public boolean isPhotoEnabled() { + return !isFilteredOut(FilterBit.PHOTO, false); + } + + public String apply(String vCard, boolean vCardType21){ + if (filter == null) return vCard; + String lines[] = vCard.split(SEPARATOR); + StringBuilder filteredVCard = new StringBuilder(); + boolean filteredOut = false; + + for (String line : lines) { + // Check whether the current property is changing (ignoring multi-line properties) + // and determine if the current property is filtered in. + if (!Character.isWhitespace(line.charAt(0)) && !line.startsWith("=")) { + String currentProp = line.split("[;:]")[0]; + filteredOut = false; + + for (FilterBit bit : FilterBit.values()) { + if (bit.prop.equals(currentProp)) { + filteredOut = isFilteredOut(bit, vCardType21); + break; } } - } - } - /*Since PBAP does not have filter bit for IM and SIP, - *removing them by default. - */ - if(vCard.toUpperCase().contains("IM")) { - for (int i=0; i < attr.length; i++) { - if(attr[i].toUpperCase().contains("IM")){ - vCard = vCard.replace(attr[i] + "\n", ""); - } - } - } - if(vCard.toUpperCase().contains("SIP")) { - for (int i=0; i < attr.length; i++) { - if(attr[i].toUpperCase().contains("SIP")){ - vCard = vCard.replace(attr[i] + "\n", ""); - } + // Since PBAP does not have filter bits for IM and SIP, + // exclude them by default. Easiest way is to exclude all + // X- fields.... + if (currentProp.startsWith("X-")) filteredOut = true; } - } - - Log.v(TAG, "Tokens after applying filter: "); - for (int i=0; i < attr.length; i++) { - if(!attr[i].equals("")){ - filteredVcard = filteredVcard.concat(attr[i] + "\n"); - } + // Build filtered vCard + if (!filteredOut) filteredVCard.append(line + SEPARATOR); } - return filteredVcard; + return filteredVCard.toString(); } } } |