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

import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IVold;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.provider.MediaStore;
import android.service.storage.ExternalStorageService;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import java.io.FileDescriptor;
import java.io.IOException;

/**
 * Controls storage sessions for users initiated by the {@link StorageManagerService}.
 * Each user on the device will be represented by a {@link StorageUserConnection}.
 */
public final class StorageSessionController {
    private static final String TAG = "StorageSessionController";

    private final Object mLock = new Object();
    private final Context mContext;
    @GuardedBy("mLock")
    private final SparseArray<StorageUserConnection> mConnections = new SparseArray<>();
    private final boolean mIsFuseEnabled;

    private volatile ComponentName mExternalStorageServiceComponent;
    private volatile String mExternalStorageServicePackageName;
    private volatile int mExternalStorageServiceAppId;
    private volatile boolean mIsResetting;

    public StorageSessionController(Context context, boolean isFuseEnabled) {
        mContext = Preconditions.checkNotNull(context);
        mIsFuseEnabled = isFuseEnabled;
    }

    /**
     * Creates and starts a storage session associated with {@code deviceFd} for {@code vol}.
     * Sessions can be started with {@link #onVolumeReady} and removed with {@link #onVolumeUnmount}
     * or {@link #onVolumeRemove}.
     *
     * Throws an {@link IllegalStateException} if a session for {@code vol} has already been created
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     *
     * Blocks until the session is started or fails
     *
     * @throws ExternalStorageServiceException if the session fails to start
     * @throws IllegalStateException if a session has already been created for {@code vol}
     */
    public void onVolumeMount(FileDescriptor deviceFd, VolumeInfo vol)
            throws ExternalStorageServiceException {
        if (!shouldHandle(vol)) {
            return;
        }

        Slog.i(TAG, "On volume mount " + vol);

        String sessionId = vol.getId();
        int userId = vol.getMountUserId();

        StorageUserConnection connection = null;
        synchronized (mLock) {
            connection = mConnections.get(userId);
            if (connection == null) {
                Slog.i(TAG, "Creating connection for user: " + userId);
                connection = new StorageUserConnection(mContext, userId, this);
                mConnections.put(userId, connection);
            }
            Slog.i(TAG, "Creating session with id: " + sessionId);
            connection.createSession(sessionId, new ParcelFileDescriptor(deviceFd),
                    vol.getPath().getPath(), vol.getInternalPath().getPath());
        }

        // At boot, a volume can be mounted before user is unlocked, in that case, we create it
        // above and save it so that we can restart all sessions when the user is unlocked
        if (mExternalStorageServiceComponent != null) {
            connection.startSession(sessionId);
        } else {
            Slog.i(TAG, "Controller not initialised, session not started " + sessionId);
        }
    }

    /**
     * Removes and returns the {@link StorageUserConnection} for {@code vol}.
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     *
     * @return the connection that was removed or {@code null} if nothing was removed
     */
    @Nullable
    public StorageUserConnection onVolumeRemove(VolumeInfo vol) {
        if (!shouldHandle(vol)) {
            return null;
        }

        Slog.i(TAG, "On volume remove " + vol);
        String sessionId = vol.getId();
        int userId = vol.getMountUserId();

        synchronized (mLock) {
            StorageUserConnection connection = mConnections.get(userId);
            if (connection != null) {
                Slog.i(TAG, "Removed session for vol with id: " + sessionId);
                connection.removeSession(sessionId);
                return connection;
            } else {
                Slog.w(TAG, "Session already removed for vol with id: " + sessionId);
                return null;
            }
        }
    }


    /**
     * Removes a storage session for {@code vol} and waits for exit.
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     *
     * Any errors are ignored
     *
     * Call {@link #onVolumeRemove} to remove the connection without waiting for exit
     */
    public void onVolumeUnmount(VolumeInfo vol) {
        StorageUserConnection connection = onVolumeRemove(vol);

        Slog.i(TAG, "On volume unmount " + vol);
        if (connection != null) {
            String sessionId = vol.getId();

            try {
                connection.removeSessionAndWait(sessionId);
            } catch (ExternalStorageServiceException e) {
                Slog.e(TAG, "Failed to end session for vol with id: " + sessionId, e);
            }
        }
    }

    /**
     * Restarts all sessions for {@code userId}.
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     *
     * This call blocks and waits for all sessions to be started, however any failures when starting
     * a session will be ignored.
     */
    public void onUnlockUser(int userId) throws ExternalStorageServiceException {
        if (!shouldHandle(null)) {
            return;
        }

        Slog.i(TAG, "On user unlock " + userId);
        if (userId == 0) {
            initExternalStorageServiceComponent();
        }

        StorageUserConnection connection = null;
        synchronized (mLock) {
            connection = mConnections.get(userId);
        }

        if (connection != null) {
            Slog.i(TAG, "Restarting all sessions for user: " + userId);
            connection.startAllSessions();
        } else {
            Slog.w(TAG, "No connection found for user: " + userId);
        }
    }

    /**
     * Resets all sessions for all users and waits for exit. This may kill the
     * {@link ExternalStorageservice} for a user if necessary to ensure all state has been reset.
     *
     * Does nothing if {@link #shouldHandle} is {@code false}
     **/
    public void onReset(IVold vold, Handler handler) {
        if (!shouldHandle(null)) {
            return;
        }

        SparseArray<StorageUserConnection> connections = new SparseArray();
        synchronized (mLock) {
            mIsResetting = true;
            Slog.i(TAG, "Started resetting external storage service...");
            for (int i = 0; i < mConnections.size(); i++) {
                connections.put(mConnections.keyAt(i), mConnections.valueAt(i));
            }
        }

        for (int i = 0; i < connections.size(); i++) {
            StorageUserConnection connection = connections.valueAt(i);
            for (String sessionId : connection.getAllSessionIds()) {
                try {
                    Slog.i(TAG, "Unmounting " + sessionId);
                    vold.unmount(sessionId);
                    Slog.i(TAG, "Unmounted " + sessionId);
                } catch (ServiceSpecificException | RemoteException e) {
                    // TODO(b/140025078): Hard reset vold?
                    Slog.e(TAG, "Failed to unmount volume: " + sessionId, e);
                }

                try {
                    Slog.i(TAG, "Exiting " + sessionId);
                    connection.removeSessionAndWait(sessionId);
                    Slog.i(TAG, "Exited " + sessionId);
                } catch (IllegalStateException | ExternalStorageServiceException e) {
                    Slog.e(TAG, "Failed to exit session: " + sessionId
                            + ". Killing MediaProvider...", e);
                    // If we failed to confirm the session exited, it is risky to proceed
                    // We kill the ExternalStorageService as a last resort
                    killExternalStorageService(connections.keyAt(i));
                    break;
                }
            }
            connection.close();
        }

        handler.removeCallbacksAndMessages(null);
        synchronized (mLock) {
            mConnections.clear();
            mIsResetting = false;
            Slog.i(TAG, "Finished resetting external storage service");
        }
    }

    private void initExternalStorageServiceComponent() throws ExternalStorageServiceException {
        Slog.i(TAG, "Initialialising...");
        ProviderInfo provider = mContext.getPackageManager().resolveContentProvider(
                MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                | PackageManager.MATCH_SYSTEM_ONLY);
        if (provider == null) {
            throw new ExternalStorageServiceException("No valid MediaStore provider found");
        }

        mExternalStorageServicePackageName = provider.applicationInfo.packageName;
        mExternalStorageServiceAppId = UserHandle.getAppId(provider.applicationInfo.uid);

        Intent intent = new Intent(ExternalStorageService.SERVICE_INTERFACE);
        intent.setPackage(mExternalStorageServicePackageName);
        ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
            throw new ExternalStorageServiceException(
                    "No valid ExternalStorageService component found");
        }

        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
        ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
        if (!Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE
                .equals(serviceInfo.permission)) {
            throw new ExternalStorageServiceException(name.flattenToShortString()
                    + " does not require permission "
                    + Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE);
        }

        mExternalStorageServiceComponent = name;
    }

    /** Returns the {@link ExternalStorageService} component name. */
    @Nullable
    public ComponentName getExternalStorageServiceComponentName() {
        return mExternalStorageServiceComponent;
    }

    private void killExternalStorageService(int userId) {
        IActivityManager am = ActivityManager.getService();
        try {
            am.killApplication(mExternalStorageServicePackageName, mExternalStorageServiceAppId,
                    userId, "storage_session_controller reset");
        } catch (RemoteException e) {
            Slog.i(TAG, "Failed to kill the ExtenalStorageService for user " + userId);
        }
    }

    /**
     * Throws an {@link IllegalStateException} if {@code path} is not ready to be accessed by
     * {@code userId}.
     */
    // TODO(b/144332951): This is not used because it is racy. Right after checking a path
    // we can call into vold with that path and the FUSE daemon can go down. Improve or remove
    public void checkPathReadyForUser(int userId, String path) {
        if (!mIsFuseEnabled) {
            return;
        }

        if (mIsResetting) {
            throw new IllegalStateException("Connection resetting for user " + userId
                    + " with path " + path);
        }

        StorageUserConnection connection = null;
        synchronized (mLock) {
            connection = mConnections.get(userId);
        }

        if (connection == null) {
            throw new IllegalStateException("Connection not ready for user " + userId
                    + " with path " + path);
        }
        connection.checkPathReady(path);
    }

    /**
     * Returns {@code true} if {@code vol} is an emulated or public volume,
     * {@code false} otherwise
     **/
    public static boolean isEmulatedOrPublic(VolumeInfo vol) {
        return vol.type == VolumeInfo.TYPE_EMULATED || vol.type == VolumeInfo.TYPE_PUBLIC;
    }

    /** Exception thrown when communication with the {@link ExternalStorageService} fails. */
    public static class ExternalStorageServiceException extends Exception {
        public ExternalStorageServiceException(Throwable cause) {
            super(cause);
        }

        public ExternalStorageServiceException(String message) {
            super(message);
        }

        public ExternalStorageServiceException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    private boolean shouldHandle(@Nullable VolumeInfo vol) {
        return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol));
    }
}
