/*
 * Copyright (C) 2020 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.vcn;

import static java.util.Objects.requireNonNull;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
import android.os.Binder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceSpecificException;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

/**
 * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks.
 *
 * <p>A VCN creates a virtualization layer to allow carriers to aggregate heterogeneous physical
 * networks, unifying them as a single carrier network. This enables infrastructure flexibility on
 * the part of carriers without impacting user connectivity, abstracting the physical network
 * technologies as an implementation detail of their public network.
 *
 * <p>Each VCN virtualizes a carrier's network by building tunnels to a carrier's core network over
 * carrier-managed physical links and supports a IP mobility layer to ensure seamless transitions
 * between the underlying networks. Each VCN is configured based on a Subscription Group (see {@link
 * android.telephony.SubscriptionManager}) and aggregates all networks that are brought up based on
 * a profile or suggestion in the specified Subscription Group.
 *
 * <p>The VCN can be configured to expose one or more {@link android.net.Network}(s), each with
 * different capabilities, allowing for APN virtualization.
 *
 * <p>If a tunnel fails to connect, or otherwise encounters a fatal error, the VCN will attempt to
 * reestablish the connection. If the tunnel still has not reconnected after a system-determined
 * timeout, the VCN Safe Mode (see below) will be entered.
 *
 * <p>The VCN Safe Mode ensures that users (and carriers) have a fallback to restore system
 * connectivity to update profiles, diagnose issues, contact support, or perform other remediation
 * tasks. In Safe Mode, the system will allow underlying cellular networks to be used as default.
 * Additionally, during Safe Mode, the VCN will continue to retry the connections, and will
 * automatically exit Safe Mode if all active tunnels connect successfully.
 */
@SystemService(Context.VCN_MANAGEMENT_SERVICE)
public class VcnManager {
    @NonNull private static final String TAG = VcnManager.class.getSimpleName();

    /**
     * Key for WiFi entry RSSI thresholds
     *
     * <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater
     * than, or equal to this threshold.
     *
     * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
     *
     * @hide
     */
    @NonNull
    public static final String VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY =
            "vcn_network_selection_wifi_entry_rssi_threshold";

    /**
     * Key for WiFi entry RSSI thresholds
     *
     * <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold,
     * the VCN will attempt to migrate away from the Carrier WiFi network.
     *
     * <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
     *
     * @hide
     */
    @NonNull
    public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY =
            "vcn_network_selection_wifi_exit_rssi_threshold";

    // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz

    private static final Map<
                    VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
            REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();

    @NonNull private final Context mContext;
    @NonNull private final IVcnManagementService mService;

    /**
     * Construct an instance of VcnManager within an application context.
     *
     * @param ctx the application context for this manager
     * @param service the VcnManagementService binder backing this manager
     *
     * @hide
     */
    public VcnManager(@NonNull Context ctx, @NonNull IVcnManagementService service) {
        mContext = requireNonNull(ctx, "missing context");
        mService = requireNonNull(service, "missing service");
    }

    /**
     * Get all currently registered VcnNetworkPolicyChangeListeners for testing purposes.
     *
     * @hide
     */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    @NonNull
    public static Map<VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
            getAllPolicyListeners() {
        return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS);
    }

    /**
     * Sets the VCN configuration for a given subscription group.
     *
     * <p>An app that has carrier privileges for any of the subscriptions in the given group may set
     * a VCN configuration. If a configuration already exists for the given subscription group, it
     * will be overridden. Any active VCN(s) may be forced to restart to use the new configuration.
     *
     * <p>This API is ONLY permitted for callers running as the primary user.
     *
     * @param subscriptionGroup the subscription group that the configuration should be applied to
     * @param config the configuration parameters for the VCN
     * @throws SecurityException if the caller does not have carrier privileges for the provided
     *     subscriptionGroup, or is not running as the primary user
     * @throws IOException if the configuration failed to be saved and persisted to disk. This may
     *     occur due to temporary disk errors, or more permanent conditions such as a full disk.
     */
    @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
    public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config)
            throws IOException {
        requireNonNull(subscriptionGroup, "subscriptionGroup was null");
        requireNonNull(config, "config was null");

        try {
            mService.setVcnConfig(subscriptionGroup, config, mContext.getOpPackageName());
        } catch (ServiceSpecificException e) {
            throw new IOException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Clears the VCN configuration for a given subscription group.
     *
     * <p>An app that has carrier privileges for any of the subscriptions in the given group may
     * clear a VCN configuration. This API is ONLY permitted for callers running as the primary
     * user. Any active VCN will be torn down.
     *
     * @param subscriptionGroup the subscription group that the configuration should be applied to
     * @throws SecurityException if the caller does not have carrier privileges, or is not running
     *     as the primary user
     * @throws IOException if the configuration failed to be cleared from disk. This may occur due
     *     to temporary disk errors, or more permanent conditions such as a full disk.
     */
    @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
    public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) throws IOException {
        requireNonNull(subscriptionGroup, "subscriptionGroup was null");

        try {
            mService.clearVcnConfig(subscriptionGroup, mContext.getOpPackageName());
        } catch (ServiceSpecificException e) {
            throw new IOException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Retrieves the list of Subscription Groups for which a VCN Configuration has been set.
     *
     * <p>The returned list will include only subscription groups for which the carrier app is
     * privileged, and which have an associated {@link VcnConfig}.
     *
     * @throws SecurityException if the caller is not running as the primary user
     */
    @NonNull
    public List<ParcelUuid> getConfiguredSubscriptionGroups() {
        try {
            return mService.getConfiguredSubscriptionGroups(mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using
    // the new VcnNetworkPolicyChangeListener API
    /**
     * VcnUnderlyingNetworkPolicyListener is the interface through which internal system components
     * can register to receive updates for VCN-underlying Network policies from the System Server.
     *
     * @hide
     */
    public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyChangeListener {}

    /**
     * Add a listener for VCN-underlying network policy updates.
     *
     * @param executor the Executor that will be used for invoking all calls to the specified
     *     Listener
     * @param listener the VcnUnderlyingNetworkPolicyListener to be added
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @throws IllegalStateException if the specified VcnUnderlyingNetworkPolicyListener is already
     *     registered
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public void addVcnUnderlyingNetworkPolicyListener(
            @NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
        addVcnNetworkPolicyChangeListener(executor, listener);
    }

    /**
     * Remove the specified VcnUnderlyingNetworkPolicyListener from VcnManager.
     *
     * <p>If the specified listener is not currently registered, this is a no-op.
     *
     * @param listener the VcnUnderlyingNetworkPolicyListener that will be removed
     * @hide
     */
    public void removeVcnUnderlyingNetworkPolicyListener(
            @NonNull VcnUnderlyingNetworkPolicyListener listener) {
        removeVcnNetworkPolicyChangeListener(listener);
    }

    /**
     * Queries the underlying network policy for a network with the given parameters.
     *
     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
     * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network
     * Provider MUST poll for the updated Network policy based on that Network's capabilities and
     * properties.
     *
     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
     *     policy for this Network.
     * @param linkProperties the LinkProperties to be used in determining the Network policy for
     *     this Network.
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @return the VcnUnderlyingNetworkPolicy to be used for this Network.
     * @hide
     */
    @NonNull
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
            @NonNull NetworkCapabilities networkCapabilities,
            @NonNull LinkProperties linkProperties) {
        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
        requireNonNull(linkProperties, "linkProperties must not be null");

        try {
            return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * VcnNetworkPolicyChangeListener is the interface through which internal system components
     * (e.g. Network Factories) can register to receive updates for VCN-underlying Network policies
     * from the System Server.
     *
     * <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks
     * should register a VcnNetworkPolicyChangeListener. VcnManager will then use this listener to
     * notify the registrant when VCN Network policies change. Upon receiving this signal, the
     * listener must check {@link VcnManager} for the current Network policy result for each of its
     * Networks via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
     *
     * @hide
     */
    @SystemApi
    public interface VcnNetworkPolicyChangeListener {
        /**
         * Notifies the implementation that the VCN's underlying Network policy has changed.
         *
         * <p>After receiving this callback, implementations should get the current {@link
         * VcnNetworkPolicyResult} via {@link #applyVcnNetworkPolicy(NetworkCapabilities,
         * LinkProperties)}.
         */
        void onPolicyChanged();
    }

    /**
     * Add a listener for VCN-underlying Network policy updates.
     *
     * <p>A {@link VcnNetworkPolicyChangeListener} is eligible to begin receiving callbacks once it
     * is registered. No callbacks are guaranteed upon registration.
     *
     * @param executor the Executor that will be used for invoking all calls to the specified
     *     Listener
     * @param listener the VcnNetworkPolicyChangeListener to be added
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @throws IllegalStateException if the specified VcnNetworkPolicyChangeListener is already
     *     registered
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public void addVcnNetworkPolicyChangeListener(
            @NonNull Executor executor, @NonNull VcnNetworkPolicyChangeListener listener) {
        requireNonNull(executor, "executor must not be null");
        requireNonNull(listener, "listener must not be null");

        VcnUnderlyingNetworkPolicyListenerBinder binder =
                new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
        if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
            throw new IllegalStateException("listener is already registered with VcnManager");
        }

        try {
            mService.addVcnUnderlyingNetworkPolicyListener(binder);
        } catch (RemoteException e) {
            REGISTERED_POLICY_LISTENERS.remove(listener);
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove the specified VcnNetworkPolicyChangeListener from VcnManager.
     *
     * <p>If the specified listener is not currently registered, this is a no-op.
     *
     * @param listener the VcnNetworkPolicyChangeListener that will be removed
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public void removeVcnNetworkPolicyChangeListener(
            @NonNull VcnNetworkPolicyChangeListener listener) {
        requireNonNull(listener, "listener must not be null");

        VcnUnderlyingNetworkPolicyListenerBinder binder =
                REGISTERED_POLICY_LISTENERS.remove(listener);
        if (binder == null) {
            return;
        }

        try {
            mService.removeVcnUnderlyingNetworkPolicyListener(binder);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Applies the network policy for a {@link android.net.Network} with the given parameters.
     *
     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
     * may have changed via {@link VcnNetworkPolicyChangeListener#onPolicyChanged()}, a Network
     * Provider MUST poll for the updated Network policy based on that Network's capabilities and
     * properties.
     *
     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
     *     policy result for this Network.
     * @param linkProperties the LinkProperties to be used in determining the Network policy result
     *     for this Network.
     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
     * @return the {@link VcnNetworkPolicyResult} to be used for this Network.
     * @hide
     */
    @NonNull
    @SystemApi
    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
    public VcnNetworkPolicyResult applyVcnNetworkPolicy(
            @NonNull NetworkCapabilities networkCapabilities,
            @NonNull LinkProperties linkProperties) {
        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
        requireNonNull(linkProperties, "linkProperties must not be null");

        final VcnUnderlyingNetworkPolicy policy =
                getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
        return new VcnNetworkPolicyResult(
                policy.isTeardownRequested(), policy.getMergedNetworkCapabilities());
    }

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        VCN_STATUS_CODE_NOT_CONFIGURED,
        VCN_STATUS_CODE_INACTIVE,
        VCN_STATUS_CODE_ACTIVE,
        VCN_STATUS_CODE_SAFE_MODE
    })
    public @interface VcnStatusCode {}

    /**
     * Value indicating that the VCN for the subscription group is not configured, or that the
     * callback is not privileged for the subscription group.
     */
    public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0;

    /**
     * Value indicating that the VCN for the subscription group is inactive.
     *
     * <p>A VCN is inactive if a {@link VcnConfig} is present for the subscription group, but the
     * provisioning package is not privileged.
     */
    public static final int VCN_STATUS_CODE_INACTIVE = 1;

    /**
     * Value indicating that the VCN for the subscription group is active.
     *
     * <p>A VCN is active if a {@link VcnConfig} is present for the subscription, the provisioning
     * package is privileged, and the VCN is not in Safe Mode. In other words, a VCN is considered
     * active while it is connecting, fully connected, and disconnecting.
     */
    public static final int VCN_STATUS_CODE_ACTIVE = 2;

    /**
     * Value indicating that the VCN for the subscription group is in Safe Mode.
     *
     * <p>A VCN will be put into Safe Mode if any of the gateway connections were unable to
     * establish a connection within a system-determined timeout (while underlying networks were
     * available).
     */
    public static final int VCN_STATUS_CODE_SAFE_MODE = 3;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
        VCN_ERROR_CODE_INTERNAL_ERROR,
        VCN_ERROR_CODE_CONFIG_ERROR,
        VCN_ERROR_CODE_NETWORK_ERROR
    })
    public @interface VcnErrorCode {}

    /**
     * Value indicating that an internal failure occurred in this Gateway Connection.
     */
    public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;

    /**
     * Value indicating that an error with this Gateway Connection's configuration occurred.
     *
     * <p>For example, this error code will be returned after authentication failures.
     */
    public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;

    /**
     * Value indicating that a Network error occurred with this Gateway Connection.
     *
     * <p>For example, this error code will be returned if an underlying {@link android.net.Network}
     * for this Gateway Connection is lost, or if an error occurs while resolving the connection
     * endpoint address.
     */
    public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2;

    /**
     * VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
     *
     * <p>VcnStatusCallbacks may be registered before {@link VcnConfig}s are provided for a
     * subscription group.
     */
    public abstract static class VcnStatusCallback {
        private VcnStatusCallbackBinder mCbBinder;

        /**
         * Invoked when status of the VCN for this callback's subscription group changes.
         *
         * @param statusCode the code for the status change encountered by this {@link
         *     VcnStatusCallback}'s subscription group. This value will be one of VCN_STATUS_CODE_*.
         */
        public abstract void onStatusChanged(@VcnStatusCode int statusCode);

        /**
         * Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
         * encounters an error.
         *
         * @param gatewayConnectionName the String GatewayConnection name for the GatewayConnection
         *     encountering an error. This will match the name for exactly one {@link
         *     VcnGatewayConnectionConfig} for the {@link VcnConfig} configured for this callback's
         *     subscription group
         * @param errorCode the code to indicate the error that occurred. This value will be one of
         *     VCN_ERROR_CODE_*.
         * @param detail Throwable to provide additional information about the error, or {@code
         *     null} if none
         */
        public abstract void onGatewayConnectionError(
                @NonNull String gatewayConnectionName,
                @VcnErrorCode int errorCode,
                @Nullable Throwable detail);
    }

    /**
     * Registers the given callback to receive status updates for the specified subscription.
     *
     * <p>Callbacks can be registered for a subscription before {@link VcnConfig}s are set for it.
     *
     * <p>A {@link VcnStatusCallback} may only be registered for one subscription at a time. {@link
     * VcnStatusCallback}s may be reused once unregistered.
     *
     * <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier
     * privileges for the specified subscription at the time of invocation.
     *
     * <p>A {@link VcnStatusCallback} is eligible to begin receiving callbacks once it is registered
     * and there is a VCN active for its specified subscription group (this may happen after the
     * callback is registered).
     *
     * <p>{@link VcnStatusCallback#onStatusChanged(int)} will be invoked on registration with the
     * current status for the specified subscription group's VCN. If the registrant is not
     * privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
     * returned.
     *
     * @param subscriptionGroup The subscription group to match for callbacks
     * @param executor The {@link Executor} to be used for invoking callbacks
     * @param callback The VcnStatusCallback to be registered
     * @throws IllegalStateException if callback is currently registered with VcnManager
     */
    public void registerVcnStatusCallback(
            @NonNull ParcelUuid subscriptionGroup,
            @NonNull Executor executor,
            @NonNull VcnStatusCallback callback) {
        requireNonNull(subscriptionGroup, "subscriptionGroup must not be null");
        requireNonNull(executor, "executor must not be null");
        requireNonNull(callback, "callback must not be null");

        synchronized (callback) {
            if (callback.mCbBinder != null) {
                throw new IllegalStateException("callback is already registered with VcnManager");
            }
            callback.mCbBinder = new VcnStatusCallbackBinder(executor, callback);

            try {
                mService.registerVcnStatusCallback(
                        subscriptionGroup, callback.mCbBinder, mContext.getOpPackageName());
            } catch (RemoteException e) {
                callback.mCbBinder = null;
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Unregisters the given callback.
     *
     * <p>Once unregistered, the callback will stop receiving status updates for the subscription it
     * was registered with.
     *
     * @param callback The callback to be unregistered
     */
    public void unregisterVcnStatusCallback(@NonNull VcnStatusCallback callback) {
        requireNonNull(callback, "callback must not be null");

        synchronized (callback) {
            if (callback.mCbBinder == null) {
                // no Binder attached to this callback, so it's not currently registered
                return;
            }

            try {
                mService.unregisterVcnStatusCallback(callback.mCbBinder);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } finally {
                callback.mCbBinder = null;
            }
        }
    }

    /**
     * Binder wrapper for added VcnNetworkPolicyChangeListeners to receive signals from System
     * Server.
     *
     * @hide
     */
    private static class VcnUnderlyingNetworkPolicyListenerBinder
            extends IVcnUnderlyingNetworkPolicyListener.Stub {
        @NonNull private final Executor mExecutor;
        @NonNull private final VcnNetworkPolicyChangeListener mListener;

        private VcnUnderlyingNetworkPolicyListenerBinder(
                Executor executor, VcnNetworkPolicyChangeListener listener) {
            mExecutor = executor;
            mListener = listener;
        }

        @Override
        public void onPolicyChanged() {
            Binder.withCleanCallingIdentity(
                    () -> mExecutor.execute(() -> mListener.onPolicyChanged()));
        }
    }

    /**
     * Binder wrapper for VcnStatusCallbacks to receive signals from VcnManagementService.
     *
     * @hide
     */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    public static class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
        @NonNull private final Executor mExecutor;
        @NonNull private final VcnStatusCallback mCallback;

        public VcnStatusCallbackBinder(
                @NonNull Executor executor, @NonNull VcnStatusCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
            Binder.withCleanCallingIdentity(
                    () -> mExecutor.execute(() -> mCallback.onStatusChanged(statusCode)));
        }

        // TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
        @Override
        public void onGatewayConnectionError(
                @NonNull String gatewayConnectionName,
                @VcnErrorCode int errorCode,
                @Nullable String exceptionClass,
                @Nullable String exceptionMessage) {
            final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage);

            Binder.withCleanCallingIdentity(
                    () ->
                            mExecutor.execute(
                                    () ->
                                            mCallback.onGatewayConnectionError(
                                                    gatewayConnectionName, errorCode, cause)));
        }

        private static Throwable createThrowableByClassName(
                @Nullable String className, @Nullable String message) {
            if (className == null) {
                return null;
            }

            try {
                Class<?> c = Class.forName(className);
                return (Throwable) c.getConstructor(String.class).newInstance(message);
            } catch (ReflectiveOperationException | ClassCastException e) {
                return new RuntimeException(className + ": " + message);
            }
        }
    }
}
