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

import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.MemoryIntArray;
import android.util.Slog;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;

import java.io.IOException;

/**
 * This class tracks changes for global/secure/system tables on a
 * per user basis and updates a shared memory region which client
 * processes can read to determine if their local caches are stale,
 */
final class GenerationRegistry {
    private static final String LOG_TAG = "GenerationTracker";

    private static final boolean DEBUG = false;

    private final Object mLock;

    @GuardedBy("mLock")
    private final SparseIntArray mKeyToIndexMap = new SparseIntArray();

    @GuardedBy("mLock")
    private MemoryIntArray mBackingStore;

    public GenerationRegistry(Object lock) {
        mLock = lock;
    }

    public void incrementGeneration(int key) {
        synchronized (mLock) {
            MemoryIntArray backingStore = getBackingStoreLocked();
            if (backingStore != null) {
                try {
                    final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
                    if (index >= 0) {
                        final int generation = backingStore.get(index) + 1;
                        backingStore.set(index, generation);
                    }
                } catch (IOException e) {
                    Slog.e(LOG_TAG, "Error updating generation id", e);
                    destroyBackingStore();
                }
            }
        }
    }

    public void addGenerationData(Bundle bundle, int key) {
        synchronized (mLock) {
            MemoryIntArray backingStore = getBackingStoreLocked();
            try {
                if (backingStore != null) {
                    final int index = getKeyIndexLocked(key, mKeyToIndexMap, backingStore);
                    if (index >= 0) {
                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
                                backingStore);
                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
                                backingStore.get(index));
                        if (DEBUG) {
                            Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
                                    + SettingsProvider.keyToString(key));
                        }
                    }
                }
            } catch (IOException e) {
                Slog.e(LOG_TAG, "Error adding generation data", e);
                destroyBackingStore();
            }
        }
    }

    public void onUserRemoved(int userId) {
        synchronized (mLock) {
            MemoryIntArray backingStore = getBackingStoreLocked();
            if (backingStore != null && mKeyToIndexMap.size() > 0) {
                try {
                    final int secureKey = SettingsProvider.makeKey(
                            SettingsProvider.SETTINGS_TYPE_SECURE, userId);
                    resetSlotForKeyLocked(secureKey, mKeyToIndexMap, backingStore);

                    final int systemKey = SettingsProvider.makeKey(
                            SettingsProvider.SETTINGS_TYPE_SYSTEM, userId);
                    resetSlotForKeyLocked(systemKey, mKeyToIndexMap, backingStore);
                } catch (IOException e) {
                    Slog.e(LOG_TAG, "Error cleaning up for user", e);
                    destroyBackingStore();
                }
            }
        }
    }

    private MemoryIntArray getBackingStoreLocked() {
        if (mBackingStore == null) {
            // One for the global table, two for system and secure tables for a
            // managed profile (managed profile is not included in the max user
            // count), ten for partially deleted users if users are quickly removed,
            // and twice max user count for system and secure.
            final int size = 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
            try {
                mBackingStore = new MemoryIntArray(size, false);
            } catch (IOException e) {
                Slog.e(LOG_TAG, "Error creating generation tracker", e);
            }
        }
        return mBackingStore;
    }

    private void destroyBackingStore() {
        if (mBackingStore != null) {
            try {
                mBackingStore.close();
            } catch (IOException e) {
                Slog.e(LOG_TAG, "Cannot close generation memory array", e);
            }
            mBackingStore = null;
        }
    }

    private static void resetSlotForKeyLocked(int key, SparseIntArray keyToIndexMap,
            MemoryIntArray backingStore) throws IOException {
        final int index = keyToIndexMap.get(key, -1);
        if (index >= 0) {
            keyToIndexMap.delete(key);
            backingStore.set(index, 0);
            if (DEBUG) {
                Slog.i(LOG_TAG, "Freed index:" + index + " for key:"
                        + SettingsProvider.keyToString(key));
            }
        }
    }

    private static int getKeyIndexLocked(int key, SparseIntArray keyToIndexMap,
            MemoryIntArray backingStore) throws IOException {
        int index = keyToIndexMap.get(key, -1);
        if (index < 0) {
            index = findNextEmptyIndex(backingStore);
            if (index >= 0) {
                backingStore.set(index, 1);
                keyToIndexMap.append(key, index);
                if (DEBUG) {
                    Slog.i(LOG_TAG, "Allocated index:" + index + " for key:"
                            + SettingsProvider.keyToString(key));
                }
            } else {
                Slog.e(LOG_TAG, "Could not allocate generation index");
            }
        }
        return index;
    }

    private static int findNextEmptyIndex(MemoryIntArray backingStore) throws IOException {
        final int size = backingStore.size();
        for (int i = 0; i < size; i++) {
            if (backingStore.get(i) == 0) {
                return i;
            }
        }
        return -1;
    }
}