Merge "Add CarrierConfig for roaming PLMNS that will need emer DDS switch" into qt-qpr1-dev
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b9f53480..495b37c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -661,6 +661,22 @@
             "android.settings.NIGHT_DISPLAY_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of Dark theme.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_DARK_THEME_SETTINGS =
+            "android.settings.DARK_THEME_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of locale.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 6a29d48..5d00370 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -242,6 +242,7 @@
         synchronized (mLock) {
             if (mDestroyed) return;
             if (mUpdateCalled) {
+                mFillView.setOnClickListener(null);
                 hide();
                 mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
             }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 3a9d4d5..bef60d9 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -414,13 +414,13 @@
             mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
                                                                        mSystemWindowInsets.bottom));
             ((ListView) mAdapterView).addFooterView(mFooterSpacer);
-        } else {
-            View emptyView = findViewById(R.id.empty);
-            if (emptyView != null) {
-                emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
-                                     + getResources().getDimensionPixelSize(
-                                             R.dimen.chooser_edge_margin_normal) * 2);
-            }
+        }
+
+        View emptyView = findViewById(R.id.empty);
+        if (emptyView != null) {
+            emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+                                 + getResources().getDimensionPixelSize(
+                                         R.dimen.chooser_edge_margin_normal) * 2);
         }
 
         return insets.consumeSystemWindowInsets();
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 59f82d4..0705773 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1138,6 +1138,8 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_accessCoarseLocation" product="tv">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them.</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_accessCoarseLocation" product="automotive">This app can get your approximate location only when it is in the foreground. These location services must be turned on and available on your car for the app to be able to use them.</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_accessCoarseLocation" product="default">This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index dc9a2ce..54fbaf3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -91,7 +91,7 @@
         boolean nightMode = (mContext.getResources().getConfiguration().uiMode
                         & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
 
-        if (isAuto) {
+        if (isAuto && !powerSave) {
             state.secondaryLabel = mContext.getResources().getString(nightMode
                     ? R.string.quick_settings_dark_mode_secondary_label_until_sunrise
                     : R.string.quick_settings_dark_mode_secondary_label_on_at_sunset);
@@ -121,7 +121,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return new Intent(Settings.ACTION_DISPLAY_SETTINGS);
+        return new Intent(Settings.ACTION_DARK_THEME_SETTINGS);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 56db8898..978cc57 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -53,6 +53,7 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.Slog;
+
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.DisableCarModeActivity;
@@ -67,8 +68,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import static android.content.Intent.ACTION_SCREEN_OFF;
-
 final class UiModeManagerService extends SystemService {
     private static final String TAG = UiModeManager.class.getSimpleName();
     private static final boolean LOG = false;
@@ -90,10 +89,15 @@
     private boolean mCarModeEnabled = false;
     private boolean mCharging = false;
     private boolean mPowerSave = false;
+    // Do not change configuration now. wait until screen turns off.
+    // This prevents jank and activity restart when the user
+    // is actively using the device
+    private boolean mWaitForScreenOff = false;
     private int mDefaultUiModeType;
     private boolean mCarModeKeepsScreenOn;
     private boolean mDeskModeKeepsScreenOn;
     private boolean mTelevision;
+    private boolean mCar;
     private boolean mWatch;
     private boolean mVrHeadset;
     private boolean mComputedNightMode;
@@ -201,24 +205,27 @@
         public void onTwilightStateChanged(@Nullable TwilightState state) {
             synchronized (mLock) {
                 if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                    final IntentFilter intentFilter =
-                            new IntentFilter(ACTION_SCREEN_OFF);
-                    getContext().registerReceiver(mOnScreenOffHandler, intentFilter);
+                    if (mCar) {
+                        updateLocked(0, 0);
+                    } else {
+                        registerScreenOffEvent();
+                    }
                 }
             }
         }
     };
 
+    /**
+     *  DO NOT USE DIRECTLY
+     *  see register registerScreenOffEvent and unregisterScreenOffEvent
+     */
     private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             synchronized (mLock) {
+                // must unregister first before updating
+                unregisterScreenOffEvent();
                 updateLocked(0, 0);
-                try {
-                    getContext().unregisterReceiver(mOnScreenOffHandler);
-                } catch (IllegalArgumentException e) {
-                    // we ignore this exception if the receiver is unregistered already.
-                }
             }
         }
     };
@@ -257,7 +264,7 @@
             int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE,
                     mNightMode, 0);
             mode = mode == UiModeManager.MODE_NIGHT_AUTO
-                    ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
+                    ? UiModeManager.MODE_NIGHT_YES : mode;
             SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode));
         }
     };
@@ -320,6 +327,7 @@
         final PackageManager pm = context.getPackageManager();
         mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
                 || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+        mCar = pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
         mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
 
         updateNightModeFromSettings(context, res, UserHandle.getCallingUserId());
@@ -328,7 +336,7 @@
         SystemServerInitThreadPool.get().submit(() -> {
             synchronized (mLock) {
                 updateConfigurationLocked();
-                sendConfigurationLocked();
+                applyConfigurationExternallyLocked();
             }
 
         }, TAG + ".onStart");
@@ -397,6 +405,22 @@
         return oldNightMode != mNightMode;
     }
 
+    private void registerScreenOffEvent() {
+        mWaitForScreenOff = true;
+        final IntentFilter intentFilter =
+                new IntentFilter(Intent.ACTION_SCREEN_OFF);
+        getContext().registerReceiver(mOnScreenOffHandler, intentFilter);
+    }
+
+    private void unregisterScreenOffEvent() {
+        mWaitForScreenOff = false;
+        try {
+            getContext().unregisterReceiver(mOnScreenOffHandler);
+        } catch (IllegalArgumentException e) {
+            // we ignore this exception if the receiver is unregistered already.
+        }
+    }
+
     private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
         @Override
         public void enableCarMode(int flags) {
@@ -475,28 +499,21 @@
                 synchronized (mLock) {
                     if (mNightMode != mode) {
                         if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                            try {
-                                getContext().unregisterReceiver(mOnScreenOffHandler);
-                            } catch (IllegalArgumentException e) {
-                                // we ignore this exception if the receiver is unregistered already.
-                            }
-                        }
-                        // Only persist setting if not in car mode
-                        if (!mCarModeEnabled) {
-                            Secure.putIntForUser(getContext().getContentResolver(),
-                                    Secure.UI_NIGHT_MODE, mode, user);
-                            Secure.putIntForUser(getContext().getContentResolver(),
-                                    OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
+                            unregisterScreenOffEvent();
                         }
 
                         mNightMode = mode;
                         mNightModeOverride = mode;
-                        //on screen off will update configuration instead
-                        if (mNightMode != UiModeManager.MODE_NIGHT_AUTO) {
+
+                        // Only persist setting if not in car mode
+                        if (!mCarModeEnabled) {
+                            persistNightMode(user);
+                        }
+                        // on screen off will update configuration instead
+                        if (mNightMode != UiModeManager.MODE_NIGHT_AUTO || mCar) {
                             updateLocked(0, 0);
                         } else {
-                            getContext().registerReceiver(
-                                    mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF));
+                            registerScreenOffEvent();
                         }
                     }
                 }
@@ -541,13 +558,11 @@
         @Override
         public boolean setNightModeActivated(boolean active) {
             synchronized (mLock) {
+                final int user = UserHandle.getCallingUserId();
                 final long ident = Binder.clearCallingIdentity();
                 try {
                     if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
-                        try {
-                            getContext().unregisterReceiver(mOnScreenOffHandler);
-                        } catch (IllegalArgumentException e) {
-                        }
+                        unregisterScreenOffEvent();
                         mNightModeOverride = active
                                 ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
                     } else if (mNightMode == UiModeManager.MODE_NIGHT_NO
@@ -558,7 +573,8 @@
                         mNightMode = UiModeManager.MODE_NIGHT_NO;
                     }
                     updateConfigurationLocked();
-                    sendConfigurationLocked();
+                    applyConfigurationExternallyLocked();
+                    persistNightMode(user);
                     return true;
                 } finally {
                     Binder.restoreCallingIdentity(ident);
@@ -644,6 +660,13 @@
         }
     }
 
+    private void persistNightMode(int user) {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.UI_NIGHT_MODE, mNightMode, user);
+        Secure.putIntForUser(getContext().getContentResolver(),
+                OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
+    }
+
     private void updateConfigurationLocked() {
         int uiMode = mDefaultUiModeType;
         if (mUiModeLocked) {
@@ -689,15 +712,14 @@
         }
 
         mCurUiMode = uiMode;
-        if (!mHoldingConfiguration) {
+        if (!mHoldingConfiguration || !mWaitForScreenOff) {
             mConfiguration.uiMode = uiMode;
         }
     }
 
-    private void sendConfigurationLocked() {
+    private void applyConfigurationExternallyLocked() {
         if (mSetUiMode != mConfiguration.uiMode) {
             mSetUiMode = mConfiguration.uiMode;
-
             try {
                 ActivityTaskManager.getService().updateConfiguration(mConfiguration);
             } catch (RemoteException e) {
@@ -877,7 +899,7 @@
         }
 
         // Send the new configuration.
-        sendConfigurationLocked();
+        applyConfigurationExternallyLocked();
 
         // If we did not start a dock app, then start dreaming if supported.
         if (category != null && !dockAppStarted) {
@@ -955,7 +977,6 @@
             final int user = UserHandle.getCallingUserId();
             Secure.putIntForUser(getContext().getContentResolver(),
                     OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
-
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index ea4f9c4..dd522b9 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -637,7 +637,7 @@
         return new Notification.Builder(context, SystemNotificationChannels.NETWORK_ALERTS)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
                 .setWhen(0)
-                .setOngoing(true)
+                .setOngoing(false)
                 .setAutoCancel(true)
                 .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color))
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 00c7548..8122374 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -486,7 +486,7 @@
 
     /* Opens the specified USB device */
     public ParcelFileDescriptor openDevice(String deviceAddress, UsbUserSettingsManager settings,
-            String packageName, int uid) {
+            String packageName, int pid, int uid) {
         synchronized (mLock) {
             if (isBlackListed(deviceAddress)) {
                 throw new SecurityException("USB device is on a restricted bus");
@@ -498,7 +498,7 @@
                         "device " + deviceAddress + " does not exist or is restricted");
             }
 
-            settings.checkPermission(device, packageName, uid);
+            settings.checkPermission(device, packageName, pid, uid);
             return nativeOpenDevice(deviceAddress);
         }
     }
diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java
index 8ca77f0..077d6b9 100644
--- a/services/usb/java/com/android/server/usb/UsbSerialReader.java
+++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java
@@ -93,7 +93,7 @@
                                 UserHandle.getUserId(uid));
 
                         if (mDevice instanceof UsbDevice) {
-                            settings.checkPermission((UsbDevice) mDevice, packageName, uid);
+                            settings.checkPermission((UsbDevice) mDevice, packageName, pid, uid);
                         } else {
                             settings.checkPermission((UsbAccessory) mDevice, uid);
                         }
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 4be68b8..13275f3 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -249,6 +249,7 @@
         if (mHostManager != null) {
             if (deviceName != null) {
                 int uid = Binder.getCallingUid();
+                int pid = Binder.getCallingPid();
                 int user = UserHandle.getUserId(uid);
 
                 long ident = clearCallingIdentity();
@@ -256,7 +257,7 @@
                     synchronized (mLock) {
                         if (mUserManager.isSameProfileGroup(user, mCurrentUserId)) {
                             fd = mHostManager.openDevice(deviceName, getSettingsForUser(user),
-                                    packageName, uid);
+                                    packageName, pid, uid);
                         } else {
                             Slog.w(TAG, "Cannot open " + deviceName + " for user " + user
                                     + " as user is not active.");
@@ -350,11 +351,12 @@
     @Override
     public boolean hasDevicePermission(UsbDevice device, String packageName) {
         final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
         final int userId = UserHandle.getUserId(uid);
 
         final long token = Binder.clearCallingIdentity();
         try {
-            return getSettingsForUser(userId).hasPermission(device, packageName, uid);
+            return getSettingsForUser(userId).hasPermission(device, packageName, pid, uid);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -376,11 +378,12 @@
     @Override
     public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
         final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
         final int userId = UserHandle.getUserId(uid);
 
         final long token = Binder.clearCallingIdentity();
         try {
-            getSettingsForUser(userId).requestPermission(device, packageName, pi, uid);
+            getSettingsForUser(userId).requestPermission(device, packageName, pi, pid, uid);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 84add88..e1bfb8a 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -127,11 +127,12 @@
      * Check for camera permission of the calling process.
      *
      * @param packageName Package name of the caller.
+     * @param pid Linux pid of the calling process.
      * @param uid Linux uid of the calling process.
      *
      * @return True in case camera permission is available, False otherwise.
      */
-    private boolean isCameraPermissionGranted(String packageName, int uid) {
+    private boolean isCameraPermissionGranted(String packageName, int pid, int uid) {
         int targetSdkVersion = android.os.Build.VERSION_CODES.P;
         try {
             ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0);
@@ -147,7 +148,8 @@
         }
 
         if (targetSdkVersion >= android.os.Build.VERSION_CODES.P) {
-            int allowed = mUserContext.checkCallingPermission(android.Manifest.permission.CAMERA);
+            int allowed = mUserContext.checkPermission(android.Manifest.permission.CAMERA, pid,
+                    uid);
             if (android.content.pm.PackageManager.PERMISSION_DENIED == allowed) {
                 Slog.i(TAG, "Camera permission required for USB video class devices");
                 return false;
@@ -157,9 +159,9 @@
         return true;
     }
 
-    public boolean hasPermission(UsbDevice device, String packageName, int uid) {
+    public boolean hasPermission(UsbDevice device, String packageName, int pid, int uid) {
         if (isCameraDevicePresent(device)) {
-            if (!isCameraPermissionGranted(packageName, uid)) {
+            if (!isCameraPermissionGranted(packageName, pid, uid)) {
                 return false;
             }
         }
@@ -171,8 +173,8 @@
         return mUsbPermissionManager.hasPermission(accessory, uid);
     }
 
-    public void checkPermission(UsbDevice device, String packageName, int uid) {
-        if (!hasPermission(device, packageName, uid)) {
+    public void checkPermission(UsbDevice device, String packageName, int pid, int uid) {
+        if (!hasPermission(device, packageName, pid, uid)) {
             throw new SecurityException("User has not given " + uid + "/" + packageName
                     + " permission to access device " + device.getDeviceName());
         }
@@ -206,11 +208,12 @@
                 accessory, canBeDefault, packageName, uid, mUserContext, pi);
     }
 
-    public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) {
+    public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int pid,
+            int uid) {
         Intent intent = new Intent();
 
         // respond immediately if permission has already been granted
-        if (hasPermission(device, packageName, uid)) {
+        if (hasPermission(device, packageName, pid, uid)) {
             intent.putExtra(UsbManager.EXTRA_DEVICE, device);
             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
             try {
@@ -221,7 +224,7 @@
             return;
         }
         if (isCameraDevicePresent(device)) {
-            if (!isCameraPermissionGranted(packageName, uid)) {
+            if (!isCameraPermissionGranted(packageName, pid, uid)) {
                 intent.putExtra(UsbManager.EXTRA_DEVICE, device);
                 intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
                 try {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index c3cfb02..80776fe 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -28,6 +28,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.StandardCharsets;
 import java.util.regex.PatternSyntaxException;
 
 /**
@@ -228,6 +229,10 @@
 
         private static final MacAddress MAC_ANY_ADDRESS =
                 MacAddress.fromString("02:00:00:00:00:00");
+        /**
+         * Maximum number of bytes allowed for a SSID.
+         */
+        private static final int MAX_SSID_BYTES = 32;
 
         private MacAddress mDeviceAddress = MAC_ANY_ADDRESS;
         private String mNetworkName = "";
@@ -279,6 +284,10 @@
                 throw new IllegalArgumentException(
                         "network name must be non-empty.");
             }
+            if (networkName.getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
+                throw new IllegalArgumentException(
+                        "network name exceeds " + MAX_SSID_BYTES + " bytes.");
+            }
             try {
                 if (!networkName.matches("^DIRECT-[a-zA-Z0-9]{2}.*")) {
                     throw new IllegalArgumentException(
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
index 41f109a..6199325 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pConfigTest.java
@@ -53,6 +53,13 @@
             fail("Unexpected IllegalArgumentException");
         }
 
+        // sunny case with maximum bytes for the network name
+        try {
+            b.setNetworkName("DIRECT-abcdefghijklmnopqrstuvwxy");
+        } catch (IllegalArgumentException e) {
+            fail("Unexpected IllegalArgumentException");
+        }
+
         // less than 9 characters.
         try {
             b.setNetworkName("DIRECT-z");
@@ -77,6 +84,12 @@
             b.setNetworkName("direct-a?");
             fail("expected IllegalArgumentException");
         } catch (IllegalArgumentException e) { }
+
+        // over maximum bytes
+        try {
+            b.setNetworkName("DIRECT-abcdefghijklmnopqrstuvwxyz");
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) { }
     }
 
     /**