Fix SSID in notification for RTL languages

Use the BidiFormatter for the SSID in the notification, as it may need
to be printed differently from the enclosing sentence in RTL languages.

Bug: 316498718
Test: atest
Change-Id: Ibac72235a19e1dc4304bd1e63fc75d019e1a2c19
diff --git a/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index fd41ee6..c5b2762 100644
--- a/service/src/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
@@ -38,6 +38,7 @@
 import android.os.UserHandle;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.text.BidiFormatter;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
@@ -87,6 +88,7 @@
 
     // The context is for the current user (system server)
     private final Context mContext;
+    private final Dependencies mDependencies;
     private final ConnectivityResources mResources;
     private final TelephonyManager mTelephonyManager;
     // The notification manager is created from a context for User.ALL, so notifications
@@ -96,7 +98,15 @@
     private final SparseIntArray mNotificationTypeMap;
 
     public NetworkNotificationManager(@NonNull final Context c, @NonNull final TelephonyManager t) {
+        this(c, t, new Dependencies());
+    }
+
+    @VisibleForTesting
+    protected NetworkNotificationManager(@NonNull final Context c,
+            @NonNull final TelephonyManager t,
+            @NonNull Dependencies dependencies) {
         mContext = c;
+        mDependencies = dependencies;
         mTelephonyManager = t;
         mNotificationManager =
                 (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */)
@@ -106,6 +116,13 @@
     }
 
     @VisibleForTesting
+    protected static class Dependencies {
+        public BidiFormatter getBidiFormatter() {
+            return BidiFormatter.getInstance();
+        }
+    }
+
+    @VisibleForTesting
     protected static int approximateTransportType(NetworkAgentInfo nai) {
         return nai.isVPN() ? TRANSPORT_VPN : getFirstTransportType(nai);
     }
@@ -174,7 +191,7 @@
                 name = extraInfo;
             } else {
                 final String ssid = WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid());
-                name = ssid == null ? "" : ssid;
+                name = ssid == null ? "" : mDependencies.getBidiFormatter().unicodeWrap(ssid);
             }
             // Only notify for Internet-capable networks.
             if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return;
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 727db58..bcdc4c5 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -27,6 +27,7 @@
 import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.SIGN_IN;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
@@ -61,6 +62,7 @@
 import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.testing.PollingCheck;
+import android.text.BidiFormatter;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.widget.TextView;
@@ -95,13 +97,14 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 
 @RunWith(DevSdkIgnoreRunner.class)
 @SmallTest
 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
 public class NetworkNotificationManagerTest {
 
-    private static final String TEST_SSID = "Test SSID";
+    private static final String TEST_SSID = "?Test SSID+";
     private static final String TEST_EXTRA_INFO = "extra";
     private static final int TEST_NOTIF_ID = 101;
     private static final String TEST_NOTIF_TAG = NetworkNotificationManager.tagFor(TEST_NOTIF_ID);
@@ -166,6 +169,7 @@
     @Mock NetworkAgentInfo mBluetoothNai;
     @Mock NetworkInfo mNetworkInfo;
     @Mock NetworkInfo mEmptyNetworkInfo;
+    @Mock NetworkNotificationManager.Dependencies mDependencies;
     ArgumentCaptor<Notification> mCaptor;
 
     NetworkNotificationManager mManager;
@@ -192,6 +196,7 @@
         doReturn(asUserCtx).when(mCtx).createContextAsUser(eq(UserHandle.ALL), anyInt());
         doReturn(mNotificationManager).when(mCtx)
                 .getSystemService(eq(Context.NOTIFICATION_SERVICE));
+        doReturn(BidiFormatter.getInstance(Locale.US)).when(mDependencies).getBidiFormatter();
         doReturn(TEST_EXTRA_INFO).when(mNetworkInfo).getExtraInfo();
         ConnectivityResources.setResourcesContextForTest(mCtx);
         doReturn(0xFF607D8B).when(mResources).getColor(anyInt(), any());
@@ -209,7 +214,7 @@
             .thenReturn(transportNames);
         when(mResources.getBoolean(R.bool.config_autoCancelNetworkNotifications)).thenReturn(true);
 
-        mManager = new NetworkNotificationManager(mCtx, mTelephonyManager);
+        mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mDependencies);
     }
 
     @After
@@ -535,6 +540,26 @@
     }
 
     @Test
+    public void testNotificationText_NoInternet_WithSsid() {
+        doReturn(null).when(mNetworkInfo).getExtraInfo();
+        doNotificationTextTest(NO_INTERNET,
+                R.string.wifi_no_internet, TEST_SSID,
+                R.string.wifi_no_internet_detailed);
+    }
+
+    @Test
+    public void testNotificationText_NoInternet_WithRtlSsid() {
+        final BidiFormatter formatter = BidiFormatter.getInstance(Locale.forLanguageTag("ar"));
+        final String wrappedString = formatter.unicodeWrap(TEST_SSID);
+        doReturn(formatter).when(mDependencies).getBidiFormatter();
+        doReturn(null).when(mNetworkInfo).getExtraInfo();
+        assertNotEquals(TEST_SSID, wrappedString);
+        doNotificationTextTest(NO_INTERNET,
+                R.string.wifi_no_internet, wrappedString,
+                R.string.wifi_no_internet_detailed);
+    }
+
+    @Test
     public void testNotificationText_Partial() {
         doNotificationTextTest(PARTIAL_CONNECTIVITY,
                 R.string.network_partial_connectivity, TEST_EXTRA_INFO,