Revert "Prioritize alternate charset when de-translating SSIDs"

Revert submission 23579364

Reason for revert: It seems more likely that actual UTF-8 SSIDs will be misinterpreted as GBK, than GBK being misinterpreted as UTF-8. This is because GBK (and the other common extended ASCII charsets like EUC-KR) has valid characters mapped to nearly every 2-byte sequence, which means any UTF-8 string with an even number of bytes has a high likelyhood of being interpreted as GBK.

The use of the "is UTF-8" bit is also not guaranteed (and seems to be uncommon), so the lack of it is not a good indication that the SSID is not UTF-8. Thus to be on the safe side, we should revert back to preferring UTF-8 over the alternate charset (which is also consistent with the OEM GBK solutions). 
 
Reverted changes: /q/submissionid:23579364

Change-Id: Idd0f3bd5a9cd9d6c0ebf577c885c46b35b3342d4
diff --git a/service/java/com/android/server/wifi/SsidTranslator.java b/service/java/com/android/server/wifi/SsidTranslator.java
index efad248..f3b21cd 100644
--- a/service/java/com/android/server/wifi/SsidTranslator.java
+++ b/service/java/com/android/server/wifi/SsidTranslator.java
@@ -48,7 +48,6 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -81,9 +80,9 @@
     private @NonNull Map<String, Charset> mMockCharsetsPerLocaleLanguage = new HashMap<>();
 
     // Maps a translated SSID to all of its BSSIDs using the alternate Charset.
-    private @NonNull Map<WifiSsid, Set<MacAddress>> mTranslatedBssidsForSsid = new ArrayMap<>();
+    private @NonNull Map<WifiSsid, Set<MacAddress>> mTranslatedBssids = new ArrayMap<>();
     // Maps a translated SSID to all of its BSSIDs not using the alternate Charset.
-    private @NonNull Map<WifiSsid, Set<MacAddress>> mUntranslatedBssidsForSsid = new ArrayMap<>();
+    private @NonNull Map<WifiSsid, Set<MacAddress>> mUntranslatedBssids = new ArrayMap<>();
     private final Map<Pair<WifiSsid, MacAddress>, Runnable> mUntranslatedBssidTimeoutRunnables =
             new ArrayMap<>();
     private final Map<Pair<WifiSsid, MacAddress>, Runnable> mTranslatedBssidTimeoutRunnables =
@@ -142,12 +141,12 @@
             mWifiHandler.removeCallbacks(runnable);
         }
         mTranslatedBssidTimeoutRunnables.clear();
-        mTranslatedBssidsForSsid.clear();
+        mTranslatedBssids.clear();
         for (Runnable runnable : mUntranslatedBssidTimeoutRunnables.values()) {
             mWifiHandler.removeCallbacks(runnable);
         }
         mUntranslatedBssidTimeoutRunnables.clear();
-        mUntranslatedBssidsForSsid.clear();
+        mUntranslatedBssids.clear();
         mCurrentLocaleAlternateCharset = null;
         // Try to find the Charset for the specific language.
         String language = null;
@@ -230,13 +229,13 @@
         }
         // Try translating the SSID from the alternate charset if it hasn't been declared as UTF-8.
         if (!isStrictUtf8
-                && !(mUntranslatedBssidsForSsid.containsKey(ssid)
-                && mUntranslatedBssidsForSsid.get(ssid).contains(bssid))) {
+                && !(mUntranslatedBssids.containsKey(ssid)
+                && mUntranslatedBssids.get(ssid).contains(bssid))) {
             WifiSsid translatedSsid =
                     translateSsid(ssid, mCurrentLocaleAlternateCharset, StandardCharsets.UTF_8);
             if (translatedSsid != null) {
                 if (bssid != null) {
-                    mTranslatedBssidsForSsid.computeIfAbsent(translatedSsid, k -> new ArraySet<>())
+                    mTranslatedBssids.computeIfAbsent(translatedSsid, k -> new ArraySet<>())
                             .add(bssid);
                     Pair<WifiSsid, MacAddress> ssidBssidPair = new Pair<>(translatedSsid, bssid);
                     Runnable oldRunnable = mTranslatedBssidTimeoutRunnables.remove(ssidBssidPair);
@@ -257,7 +256,7 @@
         }
         // SSID should be used untranslated.
         if (bssid != null) {
-            mUntranslatedBssidsForSsid.computeIfAbsent(ssid, k -> new ArraySet<>()).add(bssid);
+            mUntranslatedBssids.computeIfAbsent(ssid, k -> new ArraySet<>()).add(bssid);
             Pair<WifiSsid, MacAddress> ssidBssidPair = new Pair<>(ssid, bssid);
             Runnable oldRunnable = mUntranslatedBssidTimeoutRunnables.remove(ssidBssidPair);
             if (oldRunnable != null) {
@@ -285,13 +284,13 @@
             return;
         }
         mTranslatedBssidTimeoutRunnables.remove(mapping);
-        Set<MacAddress> bssids = mTranslatedBssidsForSsid.get(ssid);
+        Set<MacAddress> bssids = mTranslatedBssids.get(ssid);
         if (bssids == null) {
             return;
         }
         bssids.remove(bssid);
         if (bssids.isEmpty()) {
-            mTranslatedBssidsForSsid.remove(ssid);
+            mTranslatedBssids.remove(ssid);
         }
     }
 
@@ -304,59 +303,53 @@
             return;
         }
         mUntranslatedBssidTimeoutRunnables.remove(mapping);
-        Set<MacAddress> bssids = mUntranslatedBssidsForSsid.get(ssid);
+        Set<MacAddress> bssids = mUntranslatedBssids.get(ssid);
         if (bssids == null) {
             return;
         }
         bssids.remove(bssid);
         if (bssids.isEmpty()) {
-            mUntranslatedBssidsForSsid.remove(ssid);
+            mUntranslatedBssids.remove(ssid);
         }
     }
 
     /**
-     * Converts the specified translated SSID back to specified alternate Charset for the current
-     * locale language.
+     * Converts the specified translated SSID back to its original Charset if the BSSID is recorded
+     * as translated, or there are translated BSSIDs but no untranslated BSSIDs for this SSID.
      *
-     * The SSID will be returned as-is if the BSSID was already recorded as untranslated, or if all
-     * the BSSIDs associated with the SSID are untranslated, or if the SSID cannot be encoded with
-     * the alternate charset.
-     *
-     * Returns null if the given SSID is not valid both in the alternate Charset and as-is.
+     * If the BSSID has not been recorded at all, then we will return the SSID as-is.
      *
      * @param translatedSsid translated SSID.
      * @param bssid optional BSSID to look up the Charset.
-     * @return original SSID.
+     * @return original SSID. May be null if there are no valid translations back to the alternate
+     *         Charset and the translated SSID is not a valid SSID.
      */
     public synchronized @Nullable WifiSsid getOriginalSsid(
             @NonNull WifiSsid translatedSsid, @Nullable MacAddress bssid) {
         if (mCurrentLocaleAlternateCharset == null) {
             return translatedSsid.getBytes().length <= 32 ? translatedSsid : null;
         }
-        Set<MacAddress> translatedBssids = mTranslatedBssidsForSsid.get(translatedSsid);
-        if (translatedBssids == null) {
-            translatedBssids = Collections.emptySet();
-        }
-        Set<MacAddress> untranslatedBssids = mUntranslatedBssidsForSsid.get(translatedSsid);
-        if (untranslatedBssids == null) {
-            untranslatedBssids = Collections.emptySet();
-        }
-        if (!untranslatedBssids.contains(bssid)
-                && !(translatedBssids.isEmpty() && !untranslatedBssids.isEmpty())) {
+        boolean ssidWasTranslatedForSomeBssids = mTranslatedBssids.containsKey(translatedSsid);
+        boolean ssidWasTranslatedForThisBssid = ssidWasTranslatedForSomeBssids
+                && mTranslatedBssids.get(translatedSsid).contains(bssid);
+        boolean ssidNotTranslatedForSomeBssids = mUntranslatedBssids.containsKey(translatedSsid);
+        if (ssidWasTranslatedForThisBssid
+                || (ssidWasTranslatedForSomeBssids && !ssidNotTranslatedForSomeBssids)) {
             // Try to get the SSID in the alternate Charset.
             WifiSsid altCharsetSsid = translateSsid(
                     translatedSsid, StandardCharsets.UTF_8, mCurrentLocaleAlternateCharset);
-            if (altCharsetSsid != null && altCharsetSsid.getBytes().length <= 32) {
+            if (altCharsetSsid == null || altCharsetSsid.getBytes().length > 32) {
+                Log.e(TAG, "Could not translate " + translatedSsid + " back to "
+                        + mCurrentLocaleAlternateCharset + " for BSSID " + bssid);
+            } else {
                 return altCharsetSsid;
             }
         }
         // Use the translated SSID as-is
-        if (translatedSsid.getBytes().length <= 32) {
-            return translatedSsid;
+        if (translatedSsid.getBytes().length > 32) {
+            return null;
         }
-        // No valid original SSID.
-        Log.e(TAG, "getOriginalSsid: " + translatedSsid + " not a valid SSID!");
-        return null;
+        return translatedSsid;
     }
 
     /**
@@ -418,14 +411,14 @@
         pw.println("mCharsetsPerLocaleLanguage End ---");
         pw.println("mTranslatedBssids Begin ---");
         for (Map.Entry<WifiSsid, Set<MacAddress>> translatedBssidsEntry
-                : mTranslatedBssidsForSsid.entrySet()) {
+                : mTranslatedBssids.entrySet()) {
             pw.println("Translated SSID: " + translatedBssidsEntry.getKey() + ", BSSIDS: "
                     + Arrays.toString(translatedBssidsEntry.getValue().toArray()));
         }
         pw.println("mTranslatedBssids End ---");
         pw.println("mUntranslatedBssids Begin ---");
         for (Map.Entry<WifiSsid, Set<MacAddress>> untranslatedBssidsEntry
-                : mUntranslatedBssidsForSsid.entrySet()) {
+                : mUntranslatedBssids.entrySet()) {
             pw.println("Translated SSID: " + untranslatedBssidsEntry.getKey() + ", BSSIDS: "
                     + Arrays.toString(untranslatedBssidsEntry.getValue().toArray()));
         }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SsidTranslatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/SsidTranslatorTest.java
index 9443956..2280ff9 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SsidTranslatorTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SsidTranslatorTest.java
@@ -235,26 +235,26 @@
         broadcastReceiverCaptor.getValue().onReceive(mWifiContext,
                 new Intent(Intent.ACTION_LOCALE_CHANGED));
 
-        // BSSID does not match any seen scan results, use GBK.
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(gbkSsid);
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(gbkSsid);
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(gbkSsid);
-
-        // Record a BSSID using UTF-8. All non-matching BSSIDs should return UTF-8.
-        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(utf8Ssid, utf8MacAddress, true);
-        verify(mHandler, times(1)).postDelayed(
-                timeoutRunnableCaptor.capture(), eq(SsidTranslator.BSSID_CACHE_TIMEOUT_MS));
-        timeoutRunnables.add(timeoutRunnableCaptor.getValue());
+        // BSSID does not match any seen scan results, use UTF-8.
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(utf8Ssid);
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(utf8Ssid);
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(utf8Ssid);
 
-        // Record a BSSID using GBK. The GBK and null BSSIDs should return GBK now.
+        // Record a BSSID using GBK. All non-matching BSSIDs should return GBK.
         ssidTranslator.getTranslatedSsidAndRecordBssidCharset(gbkSsid, gbkMacAddress, false);
-        verify(mHandler, times(2)).postDelayed(
+        verify(mHandler, times(1)).postDelayed(
                 timeoutRunnableCaptor.capture(), eq(SsidTranslator.BSSID_CACHE_TIMEOUT_MS));
         timeoutRunnables.add(timeoutRunnableCaptor.getValue());
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(gbkSsid);
+
+        // Record a BSSID using UTF-8. The UTF-8 and null BSSIDs should return UTF-8 now.
+        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(utf8Ssid, utf8MacAddress, true);
+        verify(mHandler, times(2)).postDelayed(
+                timeoutRunnableCaptor.capture(), eq(SsidTranslator.BSSID_CACHE_TIMEOUT_MS));
+        timeoutRunnables.add(timeoutRunnableCaptor.getValue());
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(utf8Ssid);
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(utf8Ssid);
         assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(gbkSsid);
 
@@ -264,13 +264,13 @@
                 (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff});
         assertThat(ssidTranslator.getOriginalSsid(unknownSsid, null)).isEqualTo(unknownSsid);
 
-        // Timeout the scan results. Now we should return GBK SSIDs for every BSSID again.
+        // Timeout the scan results. Now we should return UTF-8 SSIDs for every BSSID again.
         for (Runnable runnable : timeoutRunnables) {
             runnable.run();
         }
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(gbkSsid);
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(gbkSsid);
-        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, null)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, utf8MacAddress)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(utf8Ssid, gbkMacAddress)).isEqualTo(utf8Ssid);
 
         // SSID is too long for any encoding, so return null.
         assertThat(ssidTranslator.getOriginalSsid(WifiSsid.fromBytes(
@@ -309,59 +309,59 @@
         WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus();
         status.setCandidate(candidate);
 
-        // BSSID does not match any seen scan results, use GBK.
+        // BSSID does not match any seen scan results, use UTF-8.
         status.setNetworkSelectionBSSID(null);
         candidate.BSSID = null;
         // Using candidate BSSID
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = "any";
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = utf8MacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = gbkMacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         // Using network selection BSSID (should override candidate)
         status.setNetworkSelectionBSSID("any");
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         status.setNetworkSelectionBSSID(utf8MacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         status.setNetworkSelectionBSSID(gbkMacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
 
-        // Record a BSSID using UTF-8. All non-matching BSSIDs should return UTF-8.
-        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(utf8Ssid, utf8MacAddress, true);
+        // Record a BSSID using GBK. All non-matching BSSIDs should return GBK.
+        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(gbkSsid, gbkMacAddress, false);
         verify(mHandler, times(1)).postDelayed(
                 timeoutRunnableCaptor.capture(), eq(SsidTranslator.BSSID_CACHE_TIMEOUT_MS));
         timeoutRunnables.add(timeoutRunnableCaptor.getValue());
         status.setNetworkSelectionBSSID(null);
         candidate.BSSID = null;
         // Using candidate BSSID
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         candidate.BSSID = "any";
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         candidate.BSSID = utf8MacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         candidate.BSSID = gbkMacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         // Using network selection BSSID (should override candidate)
         status.setNetworkSelectionBSSID("any");
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         status.setNetworkSelectionBSSID(utf8MacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
         status.setNetworkSelectionBSSID(gbkMacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
 
-        // Record a BSSID using GBK. The GBK and null BSSIDs should return GBK now.
-        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(gbkSsid, gbkMacAddress, false);
+        // Record a BSSID using UTF-8. The UTF-8 and null BSSIDs should return UTF-8 now.
+        ssidTranslator.getTranslatedSsidAndRecordBssidCharset(utf8Ssid, utf8MacAddress, true);
         verify(mHandler, times(2)).postDelayed(
                 timeoutRunnableCaptor.capture(), eq(SsidTranslator.BSSID_CACHE_TIMEOUT_MS));
         timeoutRunnables.add(timeoutRunnableCaptor.getValue());
         status.setNetworkSelectionBSSID(null);
         candidate.BSSID = null;
         // Using candidate BSSID
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = "any";
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = utf8MacAddress.toString();
         assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = gbkMacAddress.toString();
@@ -381,7 +381,7 @@
         config.SSID = unknownSsid.toString();
         assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(unknownSsid);
 
-        // Timeout the scan results. Now we should return GBK SSIDs for every BSSID again.
+        // Timeout the scan results. Now we should return UTF-8 SSIDs for every BSSID again.
         for (Runnable runnable : timeoutRunnables) {
             runnable.run();
         }
@@ -389,20 +389,20 @@
         candidate.BSSID = null;
         config.SSID = "\"安卓\"";
         // Using candidate BSSID
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = "any";
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = utf8MacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         candidate.BSSID = gbkMacAddress.toString();
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         // Using network selection BSSID (should override candidate)
         status.setNetworkSelectionBSSID("any");
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         status.setNetworkSelectionBSSID(utf8MacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
         status.setNetworkSelectionBSSID(gbkMacAddress.toString());
-        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(gbkSsid);
+        assertThat(ssidTranslator.getOriginalSsid(config)).isEqualTo(utf8Ssid);
 
         // SSID is too long for any encoding, so return null.
         config.SSID = "\"こんにちは! This is an SSID!!!!!!!!!!!!!!!!!!!!\"";