Add WifiManagerShim

Add WifiManagerShim so we can reference new Wifi APIs.

Bug: 216524590
Test: build
Change-Id: Ic884bbe78c7b3e8544a10d6a5f8801dc3d8abccc
diff --git a/Android.bp b/Android.bp
index 5d5202a..a1692e5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -176,6 +176,7 @@
         "NetworkStackApi29Shims",
         "NetworkStackApi30Shims",
         "framework-connectivity",
+        "framework-wifi",
     ],
     sdk_version: "module_31",
     visibility: ["//visibility:private"],
@@ -196,6 +197,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "framework-wifi",
     ],
     sdk_version: "module_33",
     visibility: ["//visibility:private"],
@@ -217,6 +219,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "framework-wifi",
     ],
     sdk_version: module_34_version,
     visibility: ["//visibility:private"],
@@ -249,6 +252,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "framework-wifi",
         "android.net.ipsec.ike.stubs.module_lib",
     ],
     sdk_version: "module_current",
diff --git a/apishim/29/com/android/networkstack/apishim/api29/WifiManagerShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/WifiManagerShimImpl.java
new file mode 100644
index 0000000..b205565
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/api29/WifiManagerShimImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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 com.android.networkstack.apishim.api29;
+
+import android.net.wifi.WifiManager;
+
+import com.android.networkstack.apishim.common.WifiManagerShim;
+
+/**
+ * Implementation of {@link WifiManagerShim}.
+ */
+public class WifiManagerShimImpl implements WifiManagerShim {
+    protected final WifiManager mWifiManager;
+    protected WifiManagerShimImpl(WifiManager wifiManager) {
+        mWifiManager = wifiManager;
+    }
+
+    /**
+     * Get a new instance of {@link WifiManagerShimImpl}.
+     */
+    public static WifiManagerShim newInstance(final WifiManager wifiManager) {
+        return new WifiManagerShimImpl(wifiManager);
+    }
+}
diff --git a/apishim/34/com/android/networkstack/apishim/api34/WifiManagerShimImpl.java b/apishim/34/com/android/networkstack/apishim/api34/WifiManagerShimImpl.java
new file mode 100644
index 0000000..c0adb4b
--- /dev/null
+++ b/apishim/34/com/android/networkstack/apishim/api34/WifiManagerShimImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 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 com.android.networkstack.apishim.api34;
+
+import android.net.wifi.WifiManager;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.common.WifiManagerShim;
+
+/**
+ * Implementation of {@link WifiManagerShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class WifiManagerShimImpl
+        extends com.android.networkstack.apishim.api29.WifiManagerShimImpl {
+    // Currently identical to the API 33 shim, so inherit everything
+    protected WifiManagerShimImpl(WifiManager wifiManager) {
+        super(wifiManager);
+    }
+
+    /**
+     * Get a new instance of {@link WifiManagerShimImpl}.
+     */
+    public static WifiManagerShim newInstance(final WifiManager wifiManager) {
+        if (!SdkLevel.isAtLeastU()) {
+            return com.android.networkstack.apishim.api29.WifiManagerShimImpl.newInstance(
+                    wifiManager);
+        }
+        return new WifiManagerShimImpl(wifiManager);
+    }
+}
diff --git a/apishim/35/com/android/networkstack/apishim/WifiManagerShimImpl.java b/apishim/35/com/android/networkstack/apishim/WifiManagerShimImpl.java
new file mode 100644
index 0000000..9666f48
--- /dev/null
+++ b/apishim/35/com/android/networkstack/apishim/WifiManagerShimImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 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 com.android.networkstack.apishim;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
+
+import android.net.NetworkStack;
+import android.net.TetheringManager.TetheringRequest;
+import android.net.wifi.SoftApState;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RequiresPermission;
+
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+import com.android.networkstack.apishim.common.WifiManagerShim;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of {@link WifiManagerShim}.
+ */
+// TODO: when available in all active branches: @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+@RequiresApi(Build.VERSION_CODES.CUR_DEVELOPMENT)
+public class WifiManagerShimImpl
+        extends com.android.networkstack.apishim.api34.WifiManagerShimImpl {
+    protected WifiManagerShimImpl(WifiManager wifiManager) {
+        super(wifiManager);
+    }
+
+    /**
+     * Get a new instance of {@link com.android.networkstack.apishim.WifiManagerShimImpl}.
+     */
+    public static WifiManagerShim newInstance(WifiManager wifiManager) {
+        if (!isAtLeastV()) {
+            return com.android.networkstack.apishim.api34.WifiManagerShimImpl.newInstance(
+                    wifiManager);
+        }
+        return new WifiManagerShimImpl(wifiManager);
+    }
+
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    @Override
+    public void startTetheredHotspot(
+            TetheringRequest request, Executor executor, SoftApCallbackShim callbackShim)
+            throws UnsupportedApiLevelException {
+        WifiManager.SoftApCallback callback = new WifiManager.SoftApCallback() {
+            @Override
+            public void onStateChanged(SoftApState state) {
+                callbackShim.onStateChanged(new SoftApStateShim() {
+                    @Override
+                    public int getState() {
+                        return state.getState();
+                    }
+
+                    @Override
+                    public int getFailureReason() {
+                        return state.getFailureReason();
+                    }
+
+                    @Override
+                    public String getIface() {
+                        return state.getIface();
+                    }
+
+                    @Override
+                    public TetheringRequest getTetheringRequest() {
+                        return state.getTetheringRequest();
+                    }
+                });
+            }
+        };
+        mWifiManager.startTetheredHotspot(request, executor, callback);
+    }
+}
diff --git a/apishim/common/com/android/networkstack/apishim/common/WifiManagerShim.java b/apishim/common/com/android/networkstack/apishim/common/WifiManagerShim.java
new file mode 100644
index 0000000..80b7a3a
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/WifiManagerShim.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 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 com.android.networkstack.apishim.common;
+
+import android.net.TetheringManager.TetheringRequest;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.SoftApCallback;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Interface used to access API methods in {@link android.net.wifi.WifiManager}, with
+ * appropriate fallbacks if the methods are not yet part of the released API.
+ *
+ * <p>This interface makes it easier for callers to use
+ * com.android.networkstack.apishim.WifiManagerShimImpl, as it's more obvious what methods must be
+ * implemented on each API level, and it abstracts from callers the need to reference classes that
+ * have different implementations (which also does not work well with IDEs).
+ */
+public interface WifiManagerShim {
+    /**
+     * Shim for {@link SoftApCallback#onStateChanged(SoftApState)}.
+     */
+    interface SoftApCallbackShim {
+        /**
+         * See {@link SoftApCallback#onStateChanged(SoftApState)}.
+         */
+        void onStateChanged(SoftApStateShim softApState);
+    }
+
+    /**
+     * Shim for android.net.wifi.SoftApState.
+     */
+    interface SoftApStateShim {
+        /**
+         * See SoftApState#getState().
+         */
+        int getState();
+
+        /**
+         * See SoftApState#getFailureReason().
+         */
+        int getFailureReason();
+
+        /**
+         * See SoftApState#getIface().
+         */
+        String getIface();
+
+        /**
+         * See SoftApState#getTetheringRequest().
+         */
+        TetheringRequest getTetheringRequest();
+    }
+
+    /** @see WifiManager#startTetheredHotspot(TetheringRequest, Executor, SoftApCallback)  */
+    default void startTetheredHotspot(
+            TetheringRequest request, Executor executor, SoftApCallbackShim callbackShim)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported starting from API 35");
+    }
+}