OSDN Git Service

Mercedes Benz MAP message listing workaround
authorugo_yu <ugo_yu@htc.com>
Fri, 27 May 2016 12:11:08 +0000 (20:11 +0800)
committerAndre Eisenbach <eisenbach@google.com>
Fri, 2 Sep 2016 00:50:35 +0000 (17:50 -0700)
Use case:
Sync MAP message to Benz NTG 4.5

Precondition:
1. One of SMS message contains any special characters not ASCII

Steps:
1. Connect with Benz NTG 4.5.
2. Sync SMS message from carkit.

Failure:
Carkit always shows "No Message".

Root Cause:
When this carkit requests the message listing, and any message subject has
non-ASCII special characters in it, the carkit will stop all MAP activity
and stay idle.

Fix:
Strip special characters in the subject tline in message listing
for this carkit.

This change also introduces a Java bases interop database for future
use/expansion.

Bug: 29025011
Change-Id: I4255cbeb068c82f32a68b1022285dfa723e199ec
(cherry picked from commit 4786e5fffff14d92b795084b4470b785de66dfd0)

src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java
src/com/android/bluetooth/map/BluetoothMapService.java
src/com/android/bluetooth/util/Interop.java [new file with mode: 0644]

index 236d414..eb9343e 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Date;
 import org.xmlpull.v1.XmlSerializer;
 
 import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
+import com.android.bluetooth.util.Interop;
 
 public class BluetoothMapMessageListingElement
     implements Comparable<BluetoothMapMessageListingElement> {
@@ -272,9 +273,17 @@ public class BluetoothMapMessageListingElement
                     BluetoothMapUtils.getMapHandle(mCpHandle, mType));
             if(mSubject != null){
                 String stripped = BluetoothMapUtils.stripInvalidChars(mSubject);
+
+                if (Interop.matchByAddress(Interop.INTEROP_MAP_ASCIIONLY,
+                        BluetoothMapService.getRemoteDevice().getAddress())) {
+                    stripped = stripped.replaceAll("[\\P{ASCII}&\"><]", "");
+                    if (stripped.isEmpty()) stripped = "---";
+                }
+
                 xmlMsgElement.attribute(null, "subject",
                         stripped.substring(0,  stripped.length() < 256 ? stripped.length() : 256));
             }
+
             if(mDateTime != 0)
                 xmlMsgElement.attribute(null, "datetime", this.getDateTimeString());
             if(mSenderName != null)
index 1b6155e..2721d82 100644 (file)
@@ -133,7 +133,7 @@ public class BluetoothMapService extends ProfileService {
     private HashMap<BluetoothMapAccountItem, BluetoothMapMasInstance> mMasInstanceMap =
             new HashMap<BluetoothMapAccountItem, BluetoothMapMasInstance>(1);
 
-    private BluetoothDevice mRemoteDevice = null; // The remote connected device - protect access
+    private static BluetoothDevice mRemoteDevice = null; // The remote connected device - protect access
 
     private ArrayList<BluetoothMapAccountItem> mEnabledAccounts = null;
     private static String sRemoteDeviceName = null;
@@ -476,7 +476,7 @@ public class BluetoothMapService extends ProfileService {
     protected boolean isMapStarted() {
         return !mStartError;
     }
-    public BluetoothDevice getRemoteDevice() {
+    public static BluetoothDevice getRemoteDevice() {
         return mRemoteDevice;
     }
     private void setState(int state) {
diff --git a/src/com/android/bluetooth/util/Interop.java b/src/com/android/bluetooth/util/Interop.java
new file mode 100644 (file)
index 0000000..4861c15
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bluetooth.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Centralized Bluetooth Interoperability workaround utilities and database.
+ * This is the Java version. An analagous native version can be found
+ * in /system/bt/devices/include/interop_database.h.
+ */
+public class Interop {
+
+  /**
+   * Simple interop entry consisting of a workarond id (see below)
+   * and a (partial or complete) Bluetooth device address string
+   * to match against.
+   */
+  private static class Entry {
+    String address;
+    int workaround_id;
+
+    public Entry(int workaround_id, String address) {
+      this.workaround_id = workaround_id;
+      this.address = address;
+    }
+  }
+
+  /**
+   * The actual "database" of interop entries.
+   */
+  private static List<Entry> entries = null;
+
+  /**
+   * Workaround ID for deivces which do not accept non-ASCII
+   * characters in SMS messages.
+   */
+  public static final int INTEROP_MAP_ASCIIONLY = 1;
+
+  /**
+   * Initializes the interop datbase with the relevant workaround
+   * entries.
+   * When adding entries, please provide a description for each
+   * device as to what problem the workaround addresses.
+   */
+  private static void lazyInitInteropDatabase() {
+    if (entries != null) return;
+    entries = new ArrayList<Entry>();
+
+    /** Mercedes Benz NTG 4.5 does not handle non-ASCII characters in SMS */
+    entries.add(new Entry(INTEROP_MAP_ASCIIONLY, "00:26:e8"));
+  }
+
+  /**
+   * Checks wheter a given device identified by |address| is a match
+   * for a given workaround identified by |workaround_id|.
+   * Return true if the address matches, false otherwise.
+   */
+  public static boolean matchByAddress(int workaround_id, String address) {
+    if (address == null || address.isEmpty()) return false;
+
+    lazyInitInteropDatabase();
+    for (Entry entry : entries) {
+      if (entry.workaround_id == workaround_id &&
+          entry.address.startsWith(address.toLowerCase())) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+}