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

import android.content.pm.PackageManager;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.os.storage.StorageManager;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseLongArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.ApexManager;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;

import java.util.List;

/**
 * Encapsulates the logic for initiating userdata snapshots and rollbacks via installd.
 */
@VisibleForTesting
// TODO(narayan): Reason about the failure scenarios that involve one or more IPCs to installd
// failing. We need to decide what course of action to take if calls to snapshotAppData or
// restoreAppDataSnapshot fail.
public class AppDataRollbackHelper {
    private static final String TAG = "RollbackManager";

    private final Installer mInstaller;
    private final ApexManager mApexManager;

    public AppDataRollbackHelper(Installer installer) {
        mInstaller = installer;
        mApexManager = ApexManager.getInstance();
    }

    @VisibleForTesting
    AppDataRollbackHelper(Installer installer, ApexManager apexManager) {
        mInstaller = installer;
        mApexManager = apexManager;
    }

    /**
     * Creates an app data snapshot for a specified {@code packageRollbackInfo} and the specified
     * {@code userIds}. Updates said {@code packageRollbackInfo} with the inodes of the CE user data
     * snapshot folders.
     */
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public void snapshotAppData(
            int rollbackId, PackageRollbackInfo packageRollbackInfo, int[] userIds) {
        for (int user : userIds) {
            final int storageFlags;
            if (isUserCredentialLocked(user)) {
                // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
                // across app user data until the user unlocks their device.
                Slog.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
                storageFlags = Installer.FLAG_STORAGE_DE;
                packageRollbackInfo.addPendingBackup(user);
            } else {
                storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
            }

            doSnapshot(packageRollbackInfo, user, rollbackId, storageFlags);
        }
    }

    /**
     * Restores an app data snapshot for a specified {@code packageRollbackInfo}, for a specified
     * {@code userId}.
     *
     * @return {@code true} iff. a change to the {@code packageRollbackInfo} has been made. Changes
     *         to {@code packageRollbackInfo} are restricted to the removal or addition of {@code
     *         userId} to the list of pending backups or restores.
     */
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public boolean restoreAppData(int rollbackId, PackageRollbackInfo packageRollbackInfo,
            int userId, int appId, String seInfo) {
        int storageFlags = Installer.FLAG_STORAGE_DE;

        final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
        final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores();
        boolean changedRollback = false;

        // If we still have a userdata backup pending for this user, it implies that the user
        // hasn't unlocked their device between the point of backup and the point of restore,
        // so the data cannot have changed. We simply skip restoring CE data in this case.
        if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
            pendingBackups.remove(pendingBackups.indexOf(userId));
            changedRollback = true;
        } else {
            // There's no pending CE backup for this user, which means that we successfully
            // managed to backup data for the user, which means we seek to restore it
            if (isUserCredentialLocked(userId)) {
                // We've encountered a user that hasn't unlocked on a FBE device, so we can't
                // copy across app user data until the user unlocks their device.
                pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
                changedRollback = true;
            } else {
                // This user has unlocked, we can proceed to restore both CE and DE data.
                storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
            }
        }

        doRestoreOrWipe(packageRollbackInfo, userId, rollbackId, appId, seInfo, storageFlags);

        return changedRollback;
    }

    private boolean doSnapshot(
            PackageRollbackInfo packageRollbackInfo, int userId, int rollbackId, int flags) {
        if (packageRollbackInfo.isApex()) {
            // For APEX, only snapshot CE here
            if ((flags & Installer.FLAG_STORAGE_CE) != 0) {
                long ceSnapshotInode = mApexManager.snapshotCeData(
                        userId, rollbackId, packageRollbackInfo.getPackageName());
                if (ceSnapshotInode > 0) {
                    packageRollbackInfo.putCeSnapshotInode(userId, ceSnapshotInode);
                } else {
                    return false;
                }
            }
        } else {
            // APK
            try {
                long ceSnapshotInode = mInstaller.snapshotAppData(
                        packageRollbackInfo.getPackageName(), userId, rollbackId, flags);
                if ((flags & Installer.FLAG_STORAGE_CE) != 0) {
                    packageRollbackInfo.putCeSnapshotInode(userId, ceSnapshotInode);
                }
            } catch (InstallerException ie) {
                Slog.e(TAG, "Unable to create app data snapshot for: "
                        + packageRollbackInfo.getPackageName() + ", userId: " + userId, ie);
                return false;
            }
        }
        return true;
    }

    private boolean doRestoreOrWipe(PackageRollbackInfo packageRollbackInfo, int userId,
            int rollbackId, int appId, String seInfo, int flags) {
        if (packageRollbackInfo.isApex()) {
            switch (packageRollbackInfo.getRollbackDataPolicy()) {
                case PackageManager.RollbackDataPolicy.WIPE:
                    // TODO: Implement WIPE for apex CE data
                    break;
                case PackageManager.RollbackDataPolicy.RESTORE:
                    // For APEX, only restore of CE may be done here.
                    if ((flags & Installer.FLAG_STORAGE_CE) != 0) {
                        mApexManager.restoreCeData(
                                userId, rollbackId, packageRollbackInfo.getPackageName());
                    }
                    break;
                default:
                    break;
            }
        } else {
            // APK
            try {
                switch (packageRollbackInfo.getRollbackDataPolicy()) {
                    case PackageManager.RollbackDataPolicy.WIPE:
                        mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(),
                                userId, flags, 0);
                        break;
                    case PackageManager.RollbackDataPolicy.RESTORE:

                        mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(),
                                appId, seInfo, userId, rollbackId, flags);
                        break;
                    default:
                        break;
                }
            } catch (InstallerException ie) {
                Slog.e(TAG, "Unable to restore/wipe app data: "
                        + packageRollbackInfo.getPackageName() + " policy="
                        + packageRollbackInfo.getRollbackDataPolicy(), ie);
                return false;
            }
        }
        return true;
    }

    /**
     * Deletes an app data snapshot with a given {@code rollbackId} for a specified package
     * {@code packageName} for a given {@code user}.
     */
    @GuardedBy("rollback.mLock")
    // TODO(b/136241838): Move into Rollback and synchronize there.
    public void destroyAppDataSnapshot(int rollbackId, PackageRollbackInfo packageRollbackInfo,
            int user) {
        int storageFlags = Installer.FLAG_STORAGE_DE;
        final SparseLongArray ceSnapshotInodes = packageRollbackInfo.getCeSnapshotInodes();
        long ceSnapshotInode = ceSnapshotInodes.get(user);
        if (ceSnapshotInode > 0) {
            storageFlags |= Installer.FLAG_STORAGE_CE;
        }
        try {
            mInstaller.destroyAppDataSnapshot(packageRollbackInfo.getPackageName(), user,
                    ceSnapshotInode, rollbackId, storageFlags);
            if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) {
                ceSnapshotInodes.delete(user);
            }
        } catch (InstallerException ie) {
            Slog.e(TAG, "Unable to delete app data snapshot for "
                        + packageRollbackInfo.getPackageName(), ie);
        }
    }

    /**
     * Commits the pending backups and restores for a given {@code userId} and {@code rollback}. If
     * the rollback has a pending backup, it is updated with a mapping from {@code userId} to inode
     * of the CE user data snapshot.
     *
     * @return true if any backups or restores were found for the userId
     */
    @GuardedBy("rollback.mLock")
    boolean commitPendingBackupAndRestoreForUser(int userId, Rollback rollback) {
        boolean foundBackupOrRestore = false;
        for (PackageRollbackInfo info : rollback.info.getPackages()) {
            boolean hasPendingBackup = false;
            boolean hasPendingRestore = false;
            final IntArray pendingBackupUsers = info.getPendingBackups();
            if (pendingBackupUsers != null) {
                if (pendingBackupUsers.indexOf(userId) != -1) {
                    hasPendingBackup = true;
                    foundBackupOrRestore = true;
                }
            }

            RestoreInfo ri = info.getRestoreInfo(userId);
            if (ri != null) {
                hasPendingRestore = true;
                foundBackupOrRestore = true;
            }

            if (hasPendingBackup && hasPendingRestore) {
                // Remove unnecessary backup, i.e. when user did not unlock their phone between the
                // request to backup data and the request to restore it.
                info.removePendingBackup(userId);
                info.removePendingRestoreInfo(userId);
                continue;
            }

            if (hasPendingBackup) {
                int idx = pendingBackupUsers.indexOf(userId);
                if (doSnapshot(
                        info, userId, rollback.info.getRollbackId(), Installer.FLAG_STORAGE_CE)) {
                    pendingBackupUsers.remove(idx);
                }
            }

            if (hasPendingRestore && doRestoreOrWipe(info, userId, rollback.info.getRollbackId(),
                    ri.appId, ri.seInfo, Installer.FLAG_STORAGE_CE)) {
                info.removeRestoreInfo(ri);
            }
        }
        return foundBackupOrRestore;
    }

    /**
     * @return {@code true} iff. {@code userId} is locked on an FBE device.
     */
    @VisibleForTesting
    public boolean isUserCredentialLocked(int userId) {
        return StorageManager.isFileEncryptedNativeOrEmulated()
                && !StorageManager.isUserKeyUnlocked(userId);
    }
}
