/*
 * 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.wifi;

import static android.os.Environment.getDataMiscCeDirectory;
import static android.os.Environment.getDataMiscDirectory;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AtomicFile;
import android.util.SparseArray;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
 * Class used to provide one time hooks for existing OEM devices to migrate their config store
 * data and other settings to the wifi apex.
 * @hide
 */
@SystemApi
public final class WifiMigration {
    /**
     * Directory to read the wifi config store files from under.
     */
    private static final String LEGACY_WIFI_STORE_DIRECTORY_NAME = "wifi";
    /**
     * Config store file for general shared store file.
     * AOSP Path on Android 10: /data/misc/wifi/WifiConfigStore.xml
     */
    public static final int STORE_FILE_SHARED_GENERAL = 0;
    /**
     * Config store file for softap shared store file.
     * AOSP Path on Android 10: /data/misc/wifi/softap.conf
     */
    public static final int STORE_FILE_SHARED_SOFTAP = 1;
    /**
     * Config store file for general user store file.
     * AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStore.xml
     */
    public static final int STORE_FILE_USER_GENERAL = 2;
    /**
     * Config store file for network suggestions user store file.
     * AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStoreNetworkSuggestions.xml
     */
    public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3;

    /** @hide */
    @IntDef(prefix = { "STORE_FILE_SHARED_" }, value = {
            STORE_FILE_SHARED_GENERAL,
            STORE_FILE_SHARED_SOFTAP,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SharedStoreFileId { }

    /** @hide */
    @IntDef(prefix = { "STORE_FILE_USER_" }, value = {
            STORE_FILE_USER_GENERAL,
            STORE_FILE_USER_NETWORK_SUGGESTIONS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserStoreFileId { }

    /**
     * Mapping of Store file Id to Store file names.
     *
     * NOTE: This is the default path for the files on AOSP devices. If the OEM has modified
     * the path or renamed the files, please edit this appropriately.
     */
    private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
            new SparseArray<String>() {{
                put(STORE_FILE_SHARED_GENERAL, "WifiConfigStore.xml");
                put(STORE_FILE_SHARED_SOFTAP, "WifiConfigStoreSoftAp.xml");
                put(STORE_FILE_USER_GENERAL, "WifiConfigStore.xml");
                put(STORE_FILE_USER_NETWORK_SUGGESTIONS, "WifiConfigStoreNetworkSuggestions.xml");
            }};

    /**
     * Pre-apex wifi shared folder.
     */
    private static File getLegacyWifiSharedDirectory() {
        return new File(getDataMiscDirectory(), LEGACY_WIFI_STORE_DIRECTORY_NAME);
    }

    /**
     * Pre-apex wifi user folder.
     */
    private static File getLegacyWifiUserDirectory(int userId) {
        return new File(getDataMiscCeDirectory(userId), LEGACY_WIFI_STORE_DIRECTORY_NAME);
    }

    /**
     * Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
     * data integrity.
     */
    private static AtomicFile getSharedAtomicFile(@SharedStoreFileId int storeFileId) {
        return new AtomicFile(new File(
                getLegacyWifiSharedDirectory(),
                STORE_ID_TO_FILE_NAME.get(storeFileId)));
    }

    /**
     * Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
     * data integrity.
     */
    private static AtomicFile getUserAtomicFile(@UserStoreFileId  int storeFileId, int userId) {
        return new AtomicFile(new File(
                getLegacyWifiUserDirectory(userId),
                STORE_ID_TO_FILE_NAME.get(storeFileId)));
    }

    private WifiMigration() { }

    /**
     * Load data from legacy shared wifi config store file.
     * <p>
     * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
     * java/android/net/wifi/migration_samples}.
     * </p>
     * <p>
     * Note:
     * <li>OEMs need to change the implementation of
     * {@link #convertAndRetrieveSharedConfigStoreFile(int)} only if their existing config store
     * format or file locations differs from the vanilla AOSP implementation.</li>
     * <li>The wifi apex will invoke
     * {@link #convertAndRetrieveSharedConfigStoreFile(int)}
     * method on every bootup, it is the responsibility of the OEM implementation to ensure that
     * they perform the necessary in place conversion of their config store file to conform to the
     * AOSP format. The OEM should ensure that the method should only return the
     * {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
     * <li>Once the migration is done, the apex will invoke
     * {@link #removeSharedConfigStoreFile(int)} to delete the store file.</li>
     * <li>The only relevant invocation of {@link #convertAndRetrieveSharedConfigStoreFile(int)}
     * occurs when a previously released device upgrades to the wifi apex from an OEM
     * implementation of the wifi stack.
     * <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
     * permissions, etc). Since the wifi service continues to run inside system_server process, this
     * method will be called from the same context (so ideally the file should still be accessible).
     * </li>
     *
     * @param storeFileId Identifier for the config store file. One of
     * {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
     * @return Instance of {@link InputStream} for migrating data, null if no migration is
     * necessary.
     * @throws IllegalArgumentException on invalid storeFileId.
     */
    @Nullable
    public static InputStream convertAndRetrieveSharedConfigStoreFile(
            @SharedStoreFileId int storeFileId) {
        if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId !=  STORE_FILE_SHARED_SOFTAP) {
            throw new IllegalArgumentException("Invalid shared store file id");
        }
        try {
            // OEMs should do conversions necessary here before returning the stream.
            return getSharedAtomicFile(storeFileId).openRead();
        } catch (FileNotFoundException e) {
            // Special handling for softap.conf.
            // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
            // Test devices running previous R builds however may have already migrated to the
            // XML format. So, check for that above before falling back to check for legacy file.
            if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
                return SoftApConfToXmlMigrationUtil.convert();
            }
            return null;
        }
    }

    /**
     * Remove the legacy shared wifi config store file.
     *
     * @param storeFileId Identifier for the config store file. One of
     * {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
     * @throws IllegalArgumentException on invalid storeFileId.
     */
    public static void removeSharedConfigStoreFile(@SharedStoreFileId int storeFileId) {
        if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId !=  STORE_FILE_SHARED_SOFTAP) {
            throw new IllegalArgumentException("Invalid shared store file id");
        }
        AtomicFile file = getSharedAtomicFile(storeFileId);
        if (file.exists()) {
            file.delete();
            return;
        }
        // Special handling for softap.conf.
        // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
        // Test devices running previous R builds however may have already migrated to the
        // XML format. So, check for that above before falling back to check for legacy file.
        if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
            SoftApConfToXmlMigrationUtil.remove();
        }
    }

    /**
     * Load data from legacy user wifi config store file.
     * <p>
     * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
     * java/android/net/wifi/migration_samples}.
     * </p>
     * <p>
     * Note:
     * <li>OEMs need to change the implementation of
     * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} only if their existing config
     * store format or file locations differs from the vanilla AOSP implementation.</li>
     * <li>The wifi apex will invoke
     * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)}
     * method on every bootup, it is the responsibility of the OEM implementation to ensure that
     * they perform the necessary in place conversion of their config store file to conform to the
     * AOSP format. The OEM should ensure that the method should only return the
     * {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
     * <li>Once the migration is done, the apex will invoke
     * {@link #removeUserConfigStoreFile(int, UserHandle)} to delete the store file.</li>
     * <li>The only relevant invocation of
     * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} occurs when a previously
     * released device upgrades to the wifi apex from an OEM implementation of the wifi
     * stack.
     * </li>
     * <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
     * permissions, etc). Since the wifi service continues to run inside system_server process, this
     * method will be called from the same context (so ideally the file should still be accessible).
     * </li>
     *
     * @param storeFileId Identifier for the config store file. One of
     * {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
     * @param userHandle User handle.
     * @return Instance of {@link InputStream} for migrating data, null if no migration is
     * necessary.
     * @throws IllegalArgumentException on invalid storeFileId or userHandle.
     */
    @Nullable
    public static InputStream convertAndRetrieveUserConfigStoreFile(
            @UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
        if (storeFileId != STORE_FILE_USER_GENERAL
                && storeFileId !=  STORE_FILE_USER_NETWORK_SUGGESTIONS) {
            throw new IllegalArgumentException("Invalid user store file id");
        }
        Objects.requireNonNull(userHandle);
        try {
            // OEMs should do conversions necessary here before returning the stream.
            return getUserAtomicFile(storeFileId, userHandle.getIdentifier()).openRead();
        } catch (FileNotFoundException e) {
            return null;
        }
    }

    /**
     * Remove the legacy user wifi config store file.
     *
     * @param storeFileId Identifier for the config store file. One of
     * {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
     * @param userHandle User handle.
     * @throws IllegalArgumentException on invalid storeFileId or userHandle.
    */
    public static void removeUserConfigStoreFile(
            @UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
        if (storeFileId != STORE_FILE_USER_GENERAL
                && storeFileId !=  STORE_FILE_USER_NETWORK_SUGGESTIONS) {
            throw new IllegalArgumentException("Invalid user store file id");
        }
        Objects.requireNonNull(userHandle);
        AtomicFile file = getUserAtomicFile(storeFileId, userHandle.getIdentifier());
        if (file.exists()) {
            file.delete();
        }
    }

    /**
     * Container for all the wifi settings data to migrate.
     */
    public static final class SettingsMigrationData implements Parcelable {
        private final boolean mScanAlwaysAvailable;
        private final boolean mP2pFactoryResetPending;
        private final String mP2pDeviceName;
        private final boolean mSoftApTimeoutEnabled;
        private final boolean mWakeupEnabled;
        private final boolean mScanThrottleEnabled;
        private final boolean mVerboseLoggingEnabled;

        private SettingsMigrationData(boolean scanAlwaysAvailable, boolean p2pFactoryResetPending,
                @Nullable String p2pDeviceName, boolean softApTimeoutEnabled, boolean wakeupEnabled,
                boolean scanThrottleEnabled, boolean verboseLoggingEnabled) {
            mScanAlwaysAvailable = scanAlwaysAvailable;
            mP2pFactoryResetPending = p2pFactoryResetPending;
            mP2pDeviceName = p2pDeviceName;
            mSoftApTimeoutEnabled = softApTimeoutEnabled;
            mWakeupEnabled = wakeupEnabled;
            mScanThrottleEnabled = scanThrottleEnabled;
            mVerboseLoggingEnabled = verboseLoggingEnabled;
        }

        public static final @NonNull Parcelable.Creator<SettingsMigrationData> CREATOR =
                new Parcelable.Creator<SettingsMigrationData>() {
                    @Override
                    public SettingsMigrationData createFromParcel(Parcel in) {
                        boolean scanAlwaysAvailable = in.readBoolean();
                        boolean p2pFactoryResetPending = in.readBoolean();
                        String p2pDeviceName = in.readString();
                        boolean softApTimeoutEnabled = in.readBoolean();
                        boolean wakeupEnabled = in.readBoolean();
                        boolean scanThrottleEnabled = in.readBoolean();
                        boolean verboseLoggingEnabled = in.readBoolean();
                        return new SettingsMigrationData(
                                scanAlwaysAvailable, p2pFactoryResetPending,
                                p2pDeviceName, softApTimeoutEnabled, wakeupEnabled,
                                scanThrottleEnabled, verboseLoggingEnabled);
                    }

                    @Override
                    public SettingsMigrationData[] newArray(int size) {
                        return new SettingsMigrationData[size];
                    }
                };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeBoolean(mScanAlwaysAvailable);
            dest.writeBoolean(mP2pFactoryResetPending);
            dest.writeString(mP2pDeviceName);
            dest.writeBoolean(mSoftApTimeoutEnabled);
            dest.writeBoolean(mWakeupEnabled);
            dest.writeBoolean(mScanThrottleEnabled);
            dest.writeBoolean(mVerboseLoggingEnabled);
        }

        /**
         * @return True if scans are allowed even when wifi is toggled off, false otherwise.
         */
        public boolean isScanAlwaysAvailable() {
            return mScanAlwaysAvailable;
        }

        /**
         * @return indicate whether factory reset request is pending.
         */
        public boolean isP2pFactoryResetPending() {
            return mP2pFactoryResetPending;
        }

        /**
         * @return the Wi-Fi peer-to-peer device name
         */
        public @Nullable String getP2pDeviceName() {
            return mP2pDeviceName;
        }

        /**
         * @return Whether soft AP will shut down after a timeout period when no devices are
         * connected.
         */
        public boolean isSoftApTimeoutEnabled() {
            return mSoftApTimeoutEnabled;
        }

        /**
         * @return whether Wi-Fi Wakeup feature is enabled.
         */
        public boolean isWakeUpEnabled() {
            return mWakeupEnabled;
        }

        /**
         * @return Whether wifi scan throttle is enabled or not.
         */
        public boolean isScanThrottleEnabled() {
            return mScanThrottleEnabled;
        }

        /**
         * @return Whether to enable verbose logging in Wi-Fi.
         */
        public boolean isVerboseLoggingEnabled() {
            return mVerboseLoggingEnabled;
        }

        /**
         * Builder to create instance of {@link SettingsMigrationData}.
         */
        public static final class Builder {
            private boolean mScanAlwaysAvailable;
            private boolean mP2pFactoryResetPending;
            private String mP2pDeviceName;
            private boolean mSoftApTimeoutEnabled;
            private boolean mWakeupEnabled;
            private boolean mScanThrottleEnabled;
            private boolean mVerboseLoggingEnabled;

            public Builder() {
            }

            /**
             * Setting to allow scans even when wifi is toggled off.
             *
             * @param available true if available, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setScanAlwaysAvailable(boolean available) {
                mScanAlwaysAvailable = available;
                return this;
            }

            /**
             * Indicate whether factory reset request is pending.
             *
             * @param pending true if pending, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setP2pFactoryResetPending(boolean pending) {
                mP2pFactoryResetPending = pending;
                return this;
            }

            /**
             * The Wi-Fi peer-to-peer device name
             *
             * @param name Name if set, null otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setP2pDeviceName(@Nullable String name) {
                mP2pDeviceName = name;
                return this;
            }

            /**
             * Whether soft AP will shut down after a timeout period when no devices are connected.
             *
             * @param enabled true if enabled, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setSoftApTimeoutEnabled(boolean enabled) {
                mSoftApTimeoutEnabled = enabled;
                return this;
            }

            /**
             * Value to specify if Wi-Fi Wakeup feature is enabled.
             *
             * @param enabled true if enabled, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setWakeUpEnabled(boolean enabled) {
                mWakeupEnabled = enabled;
                return this;
            }

            /**
             * Whether wifi scan throttle is enabled or not.
             *
             * @param enabled true if enabled, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setScanThrottleEnabled(boolean enabled) {
                mScanThrottleEnabled = enabled;
                return this;
            }

            /**
             * Setting to enable verbose logging in Wi-Fi.
             *
             * @param enabled true if enabled, false otherwise.
             * @return Instance of {@link Builder} to enable chaining of the builder method.
             */
            public @NonNull Builder setVerboseLoggingEnabled(boolean enabled) {
                mVerboseLoggingEnabled = enabled;
                return this;
            }

            /**
             * Build an instance of {@link SettingsMigrationData}.
             *
             * @return Instance of {@link SettingsMigrationData}.
             */
            public @NonNull SettingsMigrationData build() {
                return new SettingsMigrationData(mScanAlwaysAvailable, mP2pFactoryResetPending,
                        mP2pDeviceName, mSoftApTimeoutEnabled, mWakeupEnabled, mScanThrottleEnabled,
                        mVerboseLoggingEnabled);
            }
        }
    }

    /**
     * Load data from Settings.Global values.
     *
     * <p>
     * Note:
     * <li> This is method is invoked once on the first bootup. OEM can safely delete these settings
     * once the migration is complete. The first & only relevant invocation of
     * {@link #loadFromSettings(Context)} ()} occurs when a previously released
     * device upgrades to the wifi apex from an OEM implementation of the wifi stack.
     * </li>
     *
     * @param context Context to use for loading the settings provider.
     * @return Instance of {@link SettingsMigrationData} for migrating data.
     */
    @NonNull
    public static SettingsMigrationData loadFromSettings(@NonNull Context context) {
        if (Settings.Global.getInt(
                context.getContentResolver(), Settings.Global.WIFI_MIGRATION_COMPLETED, 0) == 1) {
            // migration already complete, ignore.
            return null;
        }
        SettingsMigrationData data = new SettingsMigrationData.Builder()
                .setScanAlwaysAvailable(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1)
                .setP2pFactoryResetPending(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET, 0) == 1)
                .setP2pDeviceName(
                        Settings.Global.getString(context.getContentResolver(),
                                Settings.Global.WIFI_P2P_DEVICE_NAME))
                .setSoftApTimeoutEnabled(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1) == 1)
                .setWakeUpEnabled(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1)
                .setScanThrottleEnabled(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.WIFI_SCAN_THROTTLE_ENABLED, 1) == 1)
                .setVerboseLoggingEnabled(
                        Settings.Global.getInt(context.getContentResolver(),
                                Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0) == 1)
                .build();
        Settings.Global.putInt(
                context.getContentResolver(), Settings.Global.WIFI_MIGRATION_COMPLETED, 1);
        return data;

    }
}
