Snap for 13264465 from 2f5a83c6ccb8c1c57f84fa28f43b0ccd7e9df584 to 25Q2-release
Change-Id: Ib7ec04b2b29bc34f3eea346a75867efb3b97c60b
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..347e497
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,2 @@
+IndentWidth: 4
+AllowShortIfStatementsOnASingleLine: WithoutElse
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/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
index 60285a8..1db5765 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
@@ -36,6 +36,7 @@
import android.net.wifi.WifiManager
import android.os.Build
import android.os.ParcelFileDescriptor
+import android.os.ParcelFileDescriptor.AutoCloseInputStream
import android.telephony.TelephonyManager
import android.telephony.TelephonyManager.SIM_STATE_UNKNOWN
import android.util.Log
@@ -46,6 +47,7 @@
import java.io.CharArrayWriter
import java.io.File
import java.io.FileReader
+import java.io.InputStream
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.io.PrintWriter
@@ -438,13 +440,44 @@
* <p>The output will be collected immediately, and exported to a test artifact file when the
* test ends.
* @param cmd The command to run. Stdout of the command will be collected.
- * @param shell The shell to run the command in.
+ * @param shell The shell to run the command in, for example "sh".
+ * @param exceptionContext An exception to write a stacktrace to the dump for context.
+ */
+ @RequiresApi(Build.VERSION_CODES.S)
+ fun collectCommandOutput(
+ cmd: String,
+ shell: String,
+ exceptionContext: Throwable? = null
+ ) = collectCommandOutput(cmd, exceptionContext) { c, outputProcessor ->
+ runCommandInShell(c, shell, outputProcessor)
+ }
+
+ /**
+ * Add the output of a command to the test data dump.
+ *
+ * <p>The output will be collected immediately, and exported to a test artifact file when the
+ * test ends.
+ *
+ * <p>Note this does not support shell pipes, redirections, or quoted arguments. See the S+
+ * overload if that is needed.
+ * @param cmd The command to run. Stdout of the command will be collected.
* @param exceptionContext An exception to write a stacktrace to the dump for context.
*/
fun collectCommandOutput(
cmd: String,
- shell: String = "sh",
exceptionContext: Throwable? = null
+ ) = collectCommandOutput(cmd, exceptionContext) { c, outputProcessor ->
+ AutoCloseInputStream(
+ InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(c)
+ ).use {
+ outputProcessor(it)
+ }
+ }
+
+ private fun collectCommandOutput(
+ cmd: String,
+ exceptionContext: Throwable? = null,
+ commandRunner: (String, (InputStream) -> Unit) -> Unit
) {
Log.i(TAG, "Collecting '$cmd' for test artifacts")
PrintWriter(buffer).let {
@@ -453,7 +486,7 @@
it.flush()
}
- runCommandInShell(cmd, shell) { stdout, _ ->
+ commandRunner(cmd) { stdout ->
stdout.copyTo(buffer)
}
}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt b/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
index fadc2ab..2b74036 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
@@ -19,8 +19,10 @@
package com.android.testutils
import android.app.UiAutomation
+import android.os.Build
import android.os.ParcelFileDescriptor.AutoCloseInputStream
import android.os.ParcelFileDescriptor.AutoCloseOutputStream
+import androidx.annotation.RequiresApi
import androidx.test.platform.app.InstrumentationRegistry
import java.io.InputStream
@@ -37,18 +39,17 @@
* when this function returns.
* @return Result of [outputProcessor].
*/
+@RequiresApi(Build.VERSION_CODES.S) // executeShellCommandRw is 31+
fun <T> runCommandInShell(
cmd: String,
shell: String = "sh",
- outputProcessor: (InputStream, InputStream) -> T,
+ outputProcessor: (InputStream) -> T,
): T {
- val (stdout, stdin, stderr) = InstrumentationRegistry.getInstrumentation().uiAutomation
- .executeShellCommandRwe(shell)
+ val (stdout, stdin) = InstrumentationRegistry.getInstrumentation().uiAutomation
+ .executeShellCommandRw(shell)
AutoCloseOutputStream(stdin).bufferedWriter().use { it.write(cmd) }
AutoCloseInputStream(stdout).use { outStream ->
- AutoCloseInputStream(stderr).use { errStream ->
- return outputProcessor(outStream, errStream)
- }
+ return outputProcessor(outStream)
}
}
@@ -57,10 +58,11 @@
*
* Overload of [runCommandInShell] that reads and returns stdout as String.
*/
+@RequiresApi(Build.VERSION_CODES.S)
fun runCommandInShell(
cmd: String,
shell: String = "sh",
-) = runCommandInShell(cmd, shell) { stdout, _ ->
+) = runCommandInShell(cmd, shell) { stdout ->
stdout.reader().use { it.readText() }
}
@@ -70,6 +72,7 @@
* This is generally only usable on devices on which [DeviceInfoUtils.isDebuggable] is true.
* @see runCommandInShell
*/
+@RequiresApi(Build.VERSION_CODES.S)
fun runCommandInRootShell(
cmd: String
) = runCommandInShell(cmd, shell = "su root sh")
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,
diff --git a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkManagerTest.java b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkManagerTest.java
index 5be8f49..6165afa 100644
--- a/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkManagerTest.java
+++ b/thread/tests/cts/src/android/net/thread/cts/ThreadNetworkManagerTest.java
@@ -43,6 +43,8 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ThreadNetworkManagerTest {
+ private static final String THREAD_NETWORK_FEATURE = "android.hardware.thread_network";
+
@Rule public DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
@@ -64,7 +66,7 @@
@Test
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public void getManager_hasThreadFeatureOnVOrHigher_returnsNonNull() {
- assumeTrue(mPackageManager.hasSystemFeature("android.hardware.thread_network"));
+ assumeTrue(mPackageManager.hasSystemFeature(THREAD_NETWORK_FEATURE));
assertThat(mManager).isNotNull();
}
@@ -81,8 +83,9 @@
@Test
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
@IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
- public void getManager_onUAndTv_returnsNonNull() {
+ public void getManager_onUAndTvWithThreadFeature_returnsNonNull() {
assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+ assumeTrue(mPackageManager.hasSystemFeature(THREAD_NETWORK_FEATURE));
assertThat(mManager).isNotNull();
}