Create DhcpOption object and make it a SystemApi

This allows OEM apps to pass their custom DHCP options for establishing
network connection.

Bug: 177278970

Test: atest FrameworksNetTests
Test: atest NetworkStackTests

Signed-off-by: Mingguang Xu <mingguangxu@google.com>
Change-Id: I2b8c38ee9a948ad6edb666312c989d27a8ff904b
diff --git a/framework/aidl-export/android/net/DhcpOption.aidl b/framework/aidl-export/android/net/DhcpOption.aidl
new file mode 100644
index 0000000..9ed0e62
--- /dev/null
+++ b/framework/aidl-export/android/net/DhcpOption.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2021, 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 android.net;
+
+parcelable DhcpOption;
+
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 7fc0382..50dd2ad 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -99,6 +99,15 @@
     field public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; // 0x3
   }
 
+  public final class DhcpOption implements android.os.Parcelable {
+    ctor public DhcpOption(byte, @Nullable byte[]);
+    method public int describeContents();
+    method public byte getType();
+    method @Nullable public byte[] getValue();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.DhcpOption> CREATOR;
+  }
+
   public final class NetworkAgentConfig implements android.os.Parcelable {
     method @Nullable public String getSubscriberId();
     method public boolean isBypassableVpn();
diff --git a/framework/api/module-lib-lint-baseline.txt b/framework/api/module-lib-lint-baseline.txt
new file mode 100644
index 0000000..c7b0db5
--- /dev/null
+++ b/framework/api/module-lib-lint-baseline.txt
@@ -0,0 +1,7 @@
+// Baseline format: 1.0
+NoByteOrShort: android.net.DhcpOption#DhcpOption(byte, byte[]) parameter #0:
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter type in android.net.DhcpOption(byte type, byte[] value)
+NoByteOrShort: android.net.DhcpOption#describeContents():
+    Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.describeContents()
+NoByteOrShort: android.net.DhcpOption#getType():
+    Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.getType()
diff --git a/framework/src/android/net/DhcpOption.java b/framework/src/android/net/DhcpOption.java
new file mode 100644
index 0000000..a125290
--- /dev/null
+++ b/framework/src/android/net/DhcpOption.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 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 android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class representing an option in the DHCP protocol.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class DhcpOption implements Parcelable {
+    private final byte mType;
+    private final byte[] mValue;
+
+    /**
+     * Constructs a DhcpOption object.
+     *
+     * @param type the type of this option
+     * @param value the value of this option. If {@code null}, DHCP packets containing this option
+     *              will include the option type in the Parameter Request List. Otherwise, DHCP
+     *              packets containing this option will include the option in the options section.
+     */
+    public DhcpOption(byte type, @Nullable byte[] value) {
+        mType = type;
+        mValue = value;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeByte(mType);
+        dest.writeByteArray(mValue);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final @NonNull Creator<DhcpOption> CREATOR =
+            new Creator<DhcpOption>() {
+                public DhcpOption createFromParcel(Parcel in) {
+                    return new DhcpOption(in.readByte(), in.createByteArray());
+                }
+
+                public DhcpOption[] newArray(int size) {
+                    return new DhcpOption[size];
+                }
+            };
+
+    /** Get the type of DHCP option */
+    public byte getType() {
+        return mType;
+    }
+
+    /** Get the value of DHCP option */
+    @Nullable public byte[] getValue() {
+        return mValue == null ? null : mValue.clone();
+    }
+}