/*
 * Copyright (C) 2016 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.server.wifi;

import static java.lang.Math.toIntExact;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.content.Context;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.UserManager;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.server.wifi.util.DataIntegrityChecker;
import com.android.server.wifi.util.XmlUtil;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.DigestException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * This class provides a mechanism to save data to persistent store files {@link StoreFile}.
 * Modules can register a {@link StoreData} instance indicating the {@StoreFile} into which they
 * want to save their data to.
 *
 * NOTE:
 * <li>Modules can register their {@StoreData} using
 * {@link WifiConfigStore#registerStoreData(StoreData)} directly, but should
 * use {@link WifiConfigManager#saveToStore(boolean)} for any writes.</li>
 * <li>{@link WifiConfigManager} controls {@link WifiConfigStore} and initiates read at bootup and
 * store file changes on user switch.</li>
 * <li>Not thread safe!</li>
 */
public class WifiConfigStore {
    /**
     * Config store file for general shared store file.
     */
    public static final int STORE_FILE_SHARED_GENERAL = 0;
    /**
     * Config store file for general user store file.
     */
    public static final int STORE_FILE_USER_GENERAL = 1;
    /**
     * Config store file for network suggestions user store file.
     */
    public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 2;

    @IntDef(prefix = { "STORE_FILE_" }, value = {
            STORE_FILE_SHARED_GENERAL,
            STORE_FILE_USER_GENERAL,
            STORE_FILE_USER_NETWORK_SUGGESTIONS
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface StoreFileId { }

    private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData";
    private static final String XML_TAG_VERSION = "Version";
    /**
     * Current config store data version. This will be incremented for any additions.
     */
    private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 1;
    /** This list of older versions will be used to restore data from older config store. */
    /**
     * First version of the config store data format.
     */
    private static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1;

    /**
     * Alarm tag to use for starting alarms for buffering file writes.
     */
    @VisibleForTesting
    public static final String BUFFERED_WRITE_ALARM_TAG = "WriteBufferAlarm";
    /**
     * Log tag.
     */
    private static final String TAG = "WifiConfigStore";
    /**
     * Directory to store the config store files in.
     */
    private static final String STORE_DIRECTORY_NAME = "wifi";
    /**
     * Time interval for buffering file writes for non-forced writes
     */
    private static final int BUFFERED_WRITE_ALARM_INTERVAL_MS = 10 * 1000;
    /**
     * Config store file name for general shared store file.
     */
    private static final String STORE_FILE_NAME_SHARED_GENERAL = "WifiConfigStore.xml";
    /**
     * Config store file name for general user store file.
     */
    private static final String STORE_FILE_NAME_USER_GENERAL = "WifiConfigStore.xml";
    /**
     * Config store file name for network suggestions user store file.
     */
    private static final String STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS =
            "WifiConfigStoreNetworkSuggestions.xml";
    /**
     * Mapping of Store file Id to Store file names.
     */
    private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
            new SparseArray<String>() {{
                put(STORE_FILE_SHARED_GENERAL, STORE_FILE_NAME_SHARED_GENERAL);
                put(STORE_FILE_USER_GENERAL, STORE_FILE_NAME_USER_GENERAL);
                put(STORE_FILE_USER_NETWORK_SUGGESTIONS, STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS);
            }};

    /**
     * Handler instance to post alarm timeouts to
     */
    private final Handler mEventHandler;
    /**
     * Alarm manager instance to start buffer timeout alarms.
     */
    private final AlarmManager mAlarmManager;
    /**
     * Clock instance to retrieve timestamps for alarms.
     */
    private final Clock mClock;
    private final WifiMetrics mWifiMetrics;
    /**
     * Shared config store file instance. There is 1 shared store file:
     * {@link #STORE_FILE_NAME_SHARED_GENERAL}.
     */
    private StoreFile mSharedStore;
    /**
     * User specific store file instances. There are 2 user store files:
     * {@link #STORE_FILE_NAME_USER_GENERAL} & {@link #STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS}.
     */
    private List<StoreFile> mUserStores;
    /**
     * Verbose logging flag.
     */
    private boolean mVerboseLoggingEnabled = false;
    /**
     * Flag to indicate if there is a buffered write pending.
     */
    private boolean mBufferedWritePending = false;
    /**
     * Alarm listener for flushing out any buffered writes.
     */
    private final AlarmManager.OnAlarmListener mBufferedWriteListener =
            new AlarmManager.OnAlarmListener() {
                public void onAlarm() {
                    try {
                        writeBufferedData();
                    } catch (IOException e) {
                        Log.wtf(TAG, "Buffered write failed", e);
                    }
                }
            };

    /**
     * List of data containers.
     */
    private final List<StoreData> mStoreDataList;

    /**
     * Create a new instance of WifiConfigStore.
     * Note: The store file instances have been made inputs to this class to ease unit-testing.
     *
     * @param context     context to use for retrieving the alarm manager.
     * @param looper      looper instance to post alarm timeouts to.
     * @param clock       clock instance to retrieve timestamps for alarms.
     * @param wifiMetrics Metrics instance.
     * @param sharedStore StoreFile instance pointing to the shared store file. This should
     *                    be retrieved using {@link #createSharedFile(UserManager)} method.
     */
    public WifiConfigStore(Context context, Looper looper, Clock clock, WifiMetrics wifiMetrics,
            StoreFile sharedStore) {

        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        mEventHandler = new Handler(looper);
        mClock = clock;
        mWifiMetrics = wifiMetrics;
        mStoreDataList = new ArrayList<>();

        // Initialize the store files.
        mSharedStore = sharedStore;
        // The user store is initialized to null, this will be set when the user unlocks and
        // CE storage is accessible via |switchUserStoresAndRead|.
        mUserStores = null;
    }

    /**
     * Set the user store files.
     * (Useful for mocking in unit tests).
     * @param userStores List of {@link StoreFile} created using {@link #createUserFiles(int,
     * UserManager)}.
     */
    public void setUserStores(@NonNull List<StoreFile> userStores) {
        Preconditions.checkNotNull(userStores);
        mUserStores = userStores;
    }

    /**
     * Register a {@link StoreData} to read/write data from/to a store. A {@link StoreData} is
     * responsible for a block of data in the store file, and provides serialization/deserialization
     * functions for those data.
     *
     * @param storeData The store data to be registered to the config store
     * @return true if registered successfully, false if the store file name is not valid.
     */
    public boolean registerStoreData(@NonNull StoreData storeData) {
        if (storeData == null) {
            Log.e(TAG, "Unable to register null store data");
            return false;
        }
        int storeFileId = storeData.getStoreFileId();
        if (STORE_ID_TO_FILE_NAME.get(storeFileId) == null) {
            Log.e(TAG, "Invalid shared store file specified" + storeFileId);
            return false;
        }
        mStoreDataList.add(storeData);
        return true;
    }

    /**
     * Helper method to create a store file instance for either the shared store or user store.
     * Note: The method creates the store directory if not already present. This may be needed for
     * user store files.
     *
     * @param storeBaseDir Base directory under which the store file is to be stored. The store file
     *                     will be at <storeBaseDir>/wifi/WifiConfigStore.xml.
     * @param fileId Identifier for the file. See {@link StoreFileId}.
     * @param userManager Instance of UserManager to check if the device is in single user mode.
     * @return new instance of the store file or null if the directory cannot be created.
     */
    private static @Nullable StoreFile createFile(File storeBaseDir, @StoreFileId int fileId,
                                                  UserManager userManager) {
        File storeDir = new File(storeBaseDir, STORE_DIRECTORY_NAME);
        if (!storeDir.exists()) {
            if (!storeDir.mkdir()) {
                Log.w(TAG, "Could not create store directory " + storeDir);
                return null;
            }
        }
        File file = new File(storeDir, STORE_ID_TO_FILE_NAME.get(fileId));
        DataIntegrityChecker dataIntegrityChecker = null;
        // Turn on integrity checking only for single user mode devices.
        if (userManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
            dataIntegrityChecker = new DataIntegrityChecker(file.getAbsolutePath());
        }
        return new StoreFile(file, fileId, dataIntegrityChecker);
    }

    /**
     * Create a new instance of the shared store file.
     *
     * @param userManager Instance of UserManager to check if the device is in single user mode.
     * @return new instance of the store file or null if the directory cannot be created.
     */
    public static @Nullable StoreFile createSharedFile(UserManager userManager) {
        return createFile(
                Environment.getDataMiscDirectory(), STORE_FILE_SHARED_GENERAL, userManager);
    }

    /**
     * Create new instances of the user specific store files.
     * The user store file is inside the user's encrypted data directory.
     *
     * @param userId userId corresponding to the currently logged-in user.
     * @param userManager Instance of UserManager to check if the device is in single user mode.
     * @return List of new instances of the store files created or null if the directory cannot be
     * created.
     */
    public static @Nullable List<StoreFile> createUserFiles(int userId, UserManager userManager) {
        List<StoreFile> storeFiles = new ArrayList<>();
        for (int fileId : Arrays.asList(
                STORE_FILE_USER_GENERAL, STORE_FILE_USER_NETWORK_SUGGESTIONS)) {
            StoreFile storeFile =
                    createFile(Environment.getDataMiscCeDirectory(userId), fileId, userManager);
            if (storeFile == null) {
                return null;
            }
            storeFiles.add(storeFile);
        }
        return storeFiles;
    }

    /**
     * Enable verbose logging.
     */
    public void enableVerboseLogging(boolean verbose) {
        mVerboseLoggingEnabled = verbose;
    }

    /**
     * API to check if any of the store files are present on the device. This can be used
     * to detect if the device needs to perform data migration from legacy stores.
     *
     * @return true if any of the store file is present, false otherwise.
     */
    public boolean areStoresPresent() {
        // Checking for the shared store file existence is sufficient since this is guaranteed
        // to be present on migrated devices.
        return mSharedStore.exists();
    }

    /**
     * Retrieve the list of {@link StoreData} instances registered for the provided
     * {@link StoreFile}.
     */
    private List<StoreData> retrieveStoreDataListForStoreFile(@NonNull StoreFile storeFile) {
        return mStoreDataList
                .stream()
                .filter(s -> s.getStoreFileId() == storeFile.mFileId)
                .collect(Collectors.toList());
    }

    /**
     * Check if any of the provided list of {@link StoreData} instances registered
     * for the provided {@link StoreFile }have indicated that they have new data to serialize.
     */
    private boolean hasNewDataToSerialize(@NonNull StoreFile storeFile) {
        List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile);
        return storeDataList.stream().anyMatch(s -> s.hasNewDataToSerialize());
    }

    /**
     * API to write the data provided by registered store data to config stores.
     * The method writes the user specific configurations to user specific config store and the
     * shared configurations to shared config store.
     *
     * @param forceSync boolean to force write the config stores now. if false, the writes are
     *                  buffered and written after the configured interval.
     */
    public void write(boolean forceSync)
            throws XmlPullParserException, IOException {
        boolean hasAnyNewData = false;
        // Serialize the provided data and send it to the respective stores. The actual write will
        // be performed later depending on the |forceSync| flag .
        if (hasNewDataToSerialize(mSharedStore)) {
            byte[] sharedDataBytes = serializeData(mSharedStore);
            mSharedStore.storeRawDataToWrite(sharedDataBytes);
            hasAnyNewData = true;
        }
        if (mUserStores != null) {
            for (StoreFile userStoreFile : mUserStores) {
                if (hasNewDataToSerialize(userStoreFile)) {
                    byte[] userDataBytes = serializeData(userStoreFile);
                    userStoreFile.storeRawDataToWrite(userDataBytes);
                    hasAnyNewData = true;
                }
            }
        }

        if (hasAnyNewData) {
            // Every write provides a new snapshot to be persisted, so |forceSync| flag overrides
            // any pending buffer writes.
            if (forceSync) {
                writeBufferedData();
            } else {
                startBufferedWriteAlarm();
            }
        } else if (forceSync && mBufferedWritePending) {
            // no new data to write, but there is a pending buffered write. So, |forceSync| should
            // flush that out.
            writeBufferedData();
        }
    }

    /**
     * Serialize all the data from all the {@link StoreData} clients registered for the provided
     * {@link StoreFile}.
     *
     * @param storeFile StoreFile that we want to write to.
     * @return byte[] of serialized bytes
     * @throws XmlPullParserException
     * @throws IOException
     */
    private byte[] serializeData(@NonNull StoreFile storeFile)
            throws XmlPullParserException, IOException {
        List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile);

        final XmlSerializer out = new FastXmlSerializer();
        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        out.setOutput(outputStream, StandardCharsets.UTF_8.name());

        XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER);
        XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION);
        for (StoreData storeData : storeDataList) {
            String tag = storeData.getName();
            XmlUtil.writeNextSectionStart(out, tag);
            storeData.serializeData(out);
            XmlUtil.writeNextSectionEnd(out, tag);
        }
        XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER);

        return outputStream.toByteArray();
    }

    /**
     * Helper method to start a buffered write alarm if one doesn't already exist.
     */
    private void startBufferedWriteAlarm() {
        if (!mBufferedWritePending) {
            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    mClock.getElapsedSinceBootMillis() + BUFFERED_WRITE_ALARM_INTERVAL_MS,
                    BUFFERED_WRITE_ALARM_TAG, mBufferedWriteListener, mEventHandler);
            mBufferedWritePending = true;
        }
    }

    /**
     * Helper method to stop a buffered write alarm if one exists.
     */
    private void stopBufferedWriteAlarm() {
        if (mBufferedWritePending) {
            mAlarmManager.cancel(mBufferedWriteListener);
            mBufferedWritePending = false;
        }
    }

    /**
     * Helper method to actually perform the writes to the file. This flushes out any write data
     * being buffered in the respective stores and cancels any pending buffer write alarms.
     */
    private void writeBufferedData() throws IOException {
        stopBufferedWriteAlarm();

        long writeStartTime = mClock.getElapsedSinceBootMillis();
        mSharedStore.writeBufferedRawData();
        if (mUserStores != null) {
            for (StoreFile userStoreFile : mUserStores) {
                userStoreFile.writeBufferedRawData();
            }
        }
        long writeTime = mClock.getElapsedSinceBootMillis() - writeStartTime;
        try {
            mWifiMetrics.noteWifiConfigStoreWriteDuration(toIntExact(writeTime));
        } catch (ArithmeticException e) {
            // Silently ignore on any overflow errors.
        }
        Log.d(TAG, "Writing to stores completed in " + writeTime + " ms.");
    }

    /**
     * API to read the store data from the config stores.
     * The method reads the user specific configurations from user specific config store and the
     * shared configurations from the shared config store.
     */
    public void read() throws XmlPullParserException, IOException {
        // Reset both share and user store data.
        resetStoreData(mSharedStore);
        if (mUserStores != null) {
            for (StoreFile userStoreFile : mUserStores) {
                resetStoreData(userStoreFile);
            }
        }

        long readStartTime = mClock.getElapsedSinceBootMillis();
        byte[] sharedDataBytes = mSharedStore.readRawData();
        deserializeData(sharedDataBytes, mSharedStore);
        if (mUserStores != null) {
            for (StoreFile userStoreFile : mUserStores) {
                byte[] userDataBytes = userStoreFile.readRawData();
                deserializeData(userDataBytes, userStoreFile);
            }
        }
        long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
        try {
            mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime));
        } catch (ArithmeticException e) {
            // Silently ignore on any overflow errors.
        }
        Log.d(TAG, "Reading from all stores completed in " + readTime + " ms.");
    }

    /**
     * Handles a user switch. This method changes the user specific store files and reads from the
     * new user's store files.
     *
     * @param userStores List of {@link StoreFile} created using {@link #createUserFiles(int,
     * UserManager)}.
     */
    public void switchUserStoresAndRead(@NonNull List<StoreFile> userStores)
            throws XmlPullParserException, IOException {
        Preconditions.checkNotNull(userStores);
        // Reset user store data.
        if (mUserStores != null) {
            for (StoreFile userStoreFile : mUserStores) {
                resetStoreData(userStoreFile);
            }
        }

        // Stop any pending buffered writes, if any.
        stopBufferedWriteAlarm();
        mUserStores = userStores;

        // Now read from the user store file.
        long readStartTime = mClock.getElapsedSinceBootMillis();
        for (StoreFile userStoreFile : mUserStores) {
            byte[] userDataBytes = userStoreFile.readRawData();
            deserializeData(userDataBytes, userStoreFile);
        }
        long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
        mWifiMetrics.noteWifiConfigStoreReadDuration(toIntExact(readTime));
        Log.d(TAG, "Reading from user stores completed in " + readTime + " ms.");
    }

    /**
     * Reset data for all {@link StoreData} instances registered for this {@link StoreFile}.
     */
    private void resetStoreData(@NonNull StoreFile storeFile) {
        for (StoreData storeData: retrieveStoreDataListForStoreFile(storeFile)) {
            storeData.resetData();
        }
    }

    // Inform all the provided store data clients that there is nothing in the store for them.
    private void indicateNoDataForStoreDatas(Collection<StoreData> storeDataSet)
            throws XmlPullParserException, IOException {
        for (StoreData storeData : storeDataSet) {
            storeData.deserializeData(null, 0);
        }
    }

    /**
     * Deserialize data from a {@link StoreFile} for all {@link StoreData} instances registered.
     *
     * @param dataBytes The data to parse
     * @param storeFile StoreFile that we read from. Will be used to retrieve the list of clients
     *                  who have data to deserialize from this file.
     *
     * @throws XmlPullParserException
     * @throws IOException
     */
    private void deserializeData(@NonNull byte[] dataBytes, @NonNull StoreFile storeFile)
            throws XmlPullParserException, IOException {
        List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile);
        if (dataBytes == null) {
            indicateNoDataForStoreDatas(storeDataList);
            return;
        }
        final XmlPullParser in = Xml.newPullParser();
        final ByteArrayInputStream inputStream = new ByteArrayInputStream(dataBytes);
        in.setInput(inputStream, StandardCharsets.UTF_8.name());

        // Start parsing the XML stream.
        int rootTagDepth = in.getDepth() + 1;
        parseDocumentStartAndVersionFromXml(in);

        String[] headerName = new String[1];
        Set<StoreData> storeDatasInvoked = new HashSet<>();
        while (XmlUtil.gotoNextSectionOrEnd(in, headerName, rootTagDepth)) {
            // There can only be 1 store data matching the tag (O indicates a fatal
            // error).
            StoreData storeData = storeDataList.stream()
                    .filter(s -> s.getName().equals(headerName[0]))
                    .findAny()
                    .orElse(null);
            if (storeData == null) {
                throw new XmlPullParserException("Unknown store data: " + headerName[0]
                        + ". List of store data: " + storeDataList);
            }
            storeData.deserializeData(in, rootTagDepth + 1);
            storeDatasInvoked.add(storeData);
        }
        // Inform all the other registered store data clients that there is nothing in the store
        // for them.
        Set<StoreData> storeDatasNotInvoked = new HashSet<>(storeDataList);
        storeDatasNotInvoked.removeAll(storeDatasInvoked);
        indicateNoDataForStoreDatas(storeDatasNotInvoked);
    }

    /**
     * Parse the document start and version from the XML stream.
     * This is used for both the shared and user config store data.
     *
     * @param in XmlPullParser instance pointing to the XML stream.
     * @return version number retrieved from the Xml stream.
     */
    private static int parseDocumentStartAndVersionFromXml(XmlPullParser in)
            throws XmlPullParserException, IOException {
        XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER);
        int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION);
        if (version < INITIAL_CONFIG_STORE_DATA_VERSION
                || version > CURRENT_CONFIG_STORE_DATA_VERSION) {
            throw new XmlPullParserException("Invalid version of data: " + version);
        }
        return version;
    }

    /**
     * Dump the local log buffer and other internal state of WifiConfigManager.
     */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Dump of WifiConfigStore");
        pw.println("WifiConfigStore - Store Data Begin ----");
        for (StoreData storeData : mStoreDataList) {
            pw.print("StoreData =>");
            pw.print(" ");
            pw.print("Name: " + storeData.getName());
            pw.print(", ");
            pw.print("File Id: " + storeData.getStoreFileId());
            pw.print(", ");
            pw.println("File Name: " + STORE_ID_TO_FILE_NAME.get(storeData.getStoreFileId()));
        }
        pw.println("WifiConfigStore - Store Data End ----");
    }

    /**
     * Class to encapsulate all file writes. This is a wrapper over {@link AtomicFile} to write/read
     * raw data from the persistent file with integrity. This class provides helper methods to
     * read/write the entire file into a byte array.
     * This helps to separate out the processing, parsing, and integrity checking from the actual
     * file writing.
     */
    public static class StoreFile {
        /**
         * File permissions to lock down the file.
         */
        private static final int FILE_MODE = 0600;
        /**
         * The store file to be written to.
         */
        private final AtomicFile mAtomicFile;
        /**
         * This is an intermediate buffer to store the data to be written.
         */
        private byte[] mWriteData;
        /**
         * Store the file name for setting the file permissions/logging purposes.
         */
        private String mFileName;
        /**
         * {@link StoreFileId} Type of store file.
         */
        private @StoreFileId int mFileId;
        /**
         * The integrity file storing integrity checking data for the store file.
         * Note: This is only turned on for single user devices.
         */
        private @Nullable DataIntegrityChecker mDataIntegrityChecker;

        public StoreFile(File file, @StoreFileId int fileId,
                         @Nullable DataIntegrityChecker dataIntegrityChecker) {
            mAtomicFile = new AtomicFile(file);
            mFileName = mAtomicFile.getBaseFile().getAbsolutePath();
            mFileId = fileId;
            mDataIntegrityChecker = dataIntegrityChecker;
        }

        /**
         * Returns whether the store file already exists on disk or not.
         *
         * @return true if it exists, false otherwise.
         */
        public boolean exists() {
            return mAtomicFile.exists();
        }


        /**
         * Read the entire raw data from the store file and return in a byte array.
         *
         * @return raw data read from the file or null if the file is not found or the data has
         *  been altered.
         * @throws IOException if an error occurs. The input stream is always closed by the method
         * even when an exception is encountered.
         */
        public byte[] readRawData() throws IOException {
            byte[] bytes = null;
            try {
                bytes = mAtomicFile.readFully();
            } catch (FileNotFoundException e) {
                return null;
            }
            if (mDataIntegrityChecker != null) {
                // Check that the file has not been altered since last writeBufferedRawData()
                try {
                    if (!mDataIntegrityChecker.isOk(bytes)) {
                        Log.wtf(TAG, "Data integrity problem with file: " + mFileName);
                        return null;
                    }
                } catch (DigestException e) {
                    // When integrity checking is introduced. The existing data will have no
                    // related integrity file for validation. Thus, we will assume the existing
                    // data is correct and immediately create the integrity file.
                    Log.i(TAG, "isOK() had no integrity data to check; thus vacuously "
                            + "true. Running update now.");
                    mDataIntegrityChecker.update(bytes);
                }
            }
            return bytes;
        }

        /**
         * Store the provided byte array to be written when {@link #writeBufferedRawData()} method
         * is invoked.
         * This intermediate step is needed to help in buffering file writes.
         *
         * @param data raw data to be written to the file.
         */
        public void storeRawDataToWrite(byte[] data) {
            mWriteData = data;
        }

        /**
         * Write the stored raw data to the store file.
         * After the write to file, the mWriteData member is reset.
         * @throws IOException if an error occurs. The output stream is always closed by the method
         * even when an exception is encountered.
         */
        public void writeBufferedRawData() throws IOException {
            if (mWriteData == null) return; // No data to write for this file.
            // Write the data to the atomic file.
            FileOutputStream out = null;
            try {
                out = mAtomicFile.startWrite();
                FileUtils.setPermissions(mFileName, FILE_MODE, -1, -1);
                out.write(mWriteData);
                mAtomicFile.finishWrite(out);
            } catch (IOException e) {
                if (out != null) {
                    mAtomicFile.failWrite(out);
                }
                throw e;
            }
            if (mDataIntegrityChecker != null) {
                // There was a legitimate change and update the integrity checker.
                mDataIntegrityChecker.update(mWriteData);
            }
            // Reset the pending write data after write.
            mWriteData = null;
        }
    }

    /**
     * Interface to be implemented by a module that contained data in the config store file.
     *
     * The module will be responsible for serializing/deserializing their own data.
     * Whenever {@link WifiConfigStore#read()} is invoked, all registered StoreData instances will
     * be notified that a read was performed via {@link StoreData#deserializeData(
     * XmlPullParser, int)} regardless of whether there is any data for them or not in the
     * store file.
     *
     * Note: StoreData clients that need a config store read to kick-off operations should wait
     * for the {@link StoreData#deserializeData(XmlPullParser, int)} invocation.
     */
    public interface StoreData {
        /**
         * Serialize a XML data block to the output stream.
         *
         * @param out The output stream to serialize the data to
         */
        void serializeData(XmlSerializer out)
                throws XmlPullParserException, IOException;

        /**
         * Deserialize a XML data block from the input stream.
         *
         * @param in The input stream to read the data from. This could be null if there is
         *           nothing in the store.
         * @param outerTagDepth The depth of the outer tag in the XML document
         * Note: This will be invoked every time a store file is read, even if there is nothing
         *                      in the store for them.
         */
        void deserializeData(@Nullable XmlPullParser in, int outerTagDepth)
                throws XmlPullParserException, IOException;

        /**
         * Reset configuration data.
         */
        void resetData();

        /**
         * Check if there is any new data to persist from the last write.
         *
         * @return true if the module has new data to persist, false otherwise.
         */
        boolean hasNewDataToSerialize();

        /**
         * Return the name of this store data.  The data will be enclosed under this tag in
         * the XML block.
         *
         * @return The name of the store data
         */
        String getName();

        /**
         * File Id where this data needs to be written to.
         * This should be one of {@link #STORE_FILE_SHARED_GENERAL},
         * {@link #STORE_FILE_USER_GENERAL} or
         * {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}.
         *
         * Note: For most uses, the shared or user general store is sufficient. Creating and
         * managing store files are expensive. Only use specific store files if you have a large
         * amount of data which may not need to be persisted frequently (or at least not as
         * frequently as the general store).
         * @return Id of the file where this data needs to be persisted.
         */
        @StoreFileId int getStoreFileId();
    }
}
