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

import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbManager;
import android.mtp.MtpDatabase;
import android.mtp.MtpServer;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.util.Log;

import androidx.annotation.GuardedBy;
import androidx.annotation.NonNull;

import com.android.internal.util.Preconditions;

import java.io.File;
import java.io.FileDescriptor;
import java.util.HashMap;

/**
 * The singleton service backing instances of MtpServer that are started for the foreground user.
 * The service has the responsibility of retrieving user storage information and managing server
 * lifetime.
 */
public class MtpService extends Service {
    private static final String TAG = "MtpService";
    private static final boolean LOGD = false;

    // We restrict PTP to these subdirectories
    private static final String[] PTP_DIRECTORIES = new String[] {
        Environment.DIRECTORY_DCIM,
        Environment.DIRECTORY_PICTURES,
    };

    private final StorageEventListener mStorageEventListener = new StorageEventListener() {
        @Override
        public void onStorageStateChanged(String path, String oldState, String newState) {
            synchronized (MtpService.this) {
                Log.d(TAG, "onStorageStateChanged " + path + " " + oldState + " -> " + newState);
                if (Environment.MEDIA_MOUNTED.equals(newState)) {
                    // Updating mVolumes variable because new storage could be inserted
                    mVolumes = StorageManager.getVolumeList(getUserId(), 0);
                    for (int i = 0; i < mVolumes.length; i++) {
                        StorageVolume volume = mVolumes[i];
                        if (volume.getPath().equals(path)) {
                            mVolumeMap.put(path, volume);
                            if (mUnlocked && (volume.isPrimary() || !mPtpMode)) {
                                addStorage(volume);
                            }
                            break;
                        }
                    }
                } else if (Environment.MEDIA_MOUNTED.equals(oldState)) {
                    if (mVolumeMap.containsKey(path)) {
                        removeStorage(mVolumeMap.remove(path));
                    }
                }
            }
        }
    };

    /**
     * Static state of MtpServer. MtpServer opens FD for MTP driver internally and we cannot open
     * multiple MtpServer at the same time. The static field used to handle the case where MtpServer
     * lives beyond the lifetime of MtpService.
     *
     * Lock MtpService.this before locking MtpService.class if needed. Otherwise it goes to
     * deadlock.
     */
    @GuardedBy("MtpService.class")
    private static ServerHolder sServerHolder;

    private StorageManager mStorageManager;

    @GuardedBy("this")
    private boolean mUnlocked;
    @GuardedBy("this")
    private boolean mPtpMode;

    // A map of user volumes that are currently mounted.
    @GuardedBy("this")
    private HashMap<String, StorageVolume> mVolumeMap;

    // All user volumes in existence, in any state.
    @GuardedBy("this")
    private StorageVolume[] mVolumes;

    @Override
    public void onCreate() {
        mVolumes = StorageManager.getVolumeList(getUserId(), 0);
        mVolumeMap = new HashMap<>();

        mStorageManager = this.getSystemService(StorageManager.class);
        mStorageManager.registerListener(mStorageEventListener);
    }

    @Override
    public void onDestroy() {
        mStorageManager.unregisterListener(mStorageEventListener);
        synchronized (MtpService.class) {
            if (sServerHolder != null) {
                sServerHolder.database.setServer(null);
            }
        }
    }

    @Override
    public synchronized int onStartCommand(Intent intent, int flags, int startId) {
        mUnlocked = intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false);
        mPtpMode = intent.getBooleanExtra(UsbManager.USB_FUNCTION_PTP, false);

        for (StorageVolume v : mVolumes) {
            if (v.getState().equals(Environment.MEDIA_MOUNTED)) {
                mVolumeMap.put(v.getPath(), v);
            }
        }
        String[] subdirs = null;
        if (mPtpMode) {
            Environment.UserEnvironment env = new Environment.UserEnvironment(getUserId());
            int count = PTP_DIRECTORIES.length;
            subdirs = new String[count];
            for (int i = 0; i < count; i++) {
                File file = env.buildExternalStoragePublicDirs(PTP_DIRECTORIES[i])[0];
                // make sure this directory exists
                file.mkdirs();
                subdirs[i] = file.getName();
            }
        }
        final StorageVolume primary = StorageManager.getPrimaryVolume(mVolumes);
        startServer(primary, subdirs);
        return START_REDELIVER_INTENT;
    }

    private synchronized void startServer(StorageVolume primary, String[] subdirs) {
        if (!(UserHandle.myUserId() == ActivityManager.getCurrentUser())) {
            return;
        }
        synchronized (MtpService.class) {
            if (sServerHolder != null) {
                if (LOGD) {
                    Log.d(TAG, "Cannot launch second MTP server.");
                }
                // Previously executed MtpServer is still running. It will be terminated
                // because MTP device FD will become invalid soon. Also MtpService will get new
                // intent after that when UsbDeviceManager configures USB with new state.
                return;
            }

            Log.d(TAG, "starting MTP server in " + (mPtpMode ? "PTP mode" : "MTP mode") +
                    " with storage " + primary.getPath() + (mUnlocked ? " unlocked" : "") + " as user " + UserHandle.myUserId());

            final MtpDatabase database = new MtpDatabase(this, subdirs);
            IUsbManager usbMgr = IUsbManager.Stub.asInterface(ServiceManager.getService(
                    Context.USB_SERVICE));
            ParcelFileDescriptor controlFd = null;
            try {
                controlFd = usbMgr.getControlFd(
                        mPtpMode ? UsbManager.FUNCTION_PTP : UsbManager.FUNCTION_MTP);
            } catch (RemoteException e) {
                Log.e(TAG, "Error communicating with UsbManager: " + e);
            }
            FileDescriptor fd = null;
            if (controlFd == null) {
                Log.i(TAG, "Couldn't get control FD!");
            } else {
                fd = controlFd.getFileDescriptor();
            }

            final MtpServer server =
                    new MtpServer(database, fd, mPtpMode,
                            new OnServerTerminated(), Build.MANUFACTURER,
                            Build.MODEL, "1.0");
            database.setServer(server);
            sServerHolder = new ServerHolder(server, database);

            // Add currently mounted and enabled storages to the server
            if (mUnlocked) {
                for (StorageVolume v : mVolumeMap.values()) {
                    addStorage(v);
                }
            }
            server.start();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new Binder();
    }

    private void addStorage(StorageVolume volume) {
        Log.v(TAG, "Adding MTP storage:" + volume.getPath());
        synchronized (MtpService.class) {
            if (sServerHolder != null) {
                sServerHolder.database.addStorage(volume);
            }
        }
    }

    private void removeStorage(StorageVolume volume) {
        synchronized (MtpService.class) {
            if (sServerHolder != null) {
                sServerHolder.database.removeStorage(volume);
            }
        }
    }

    private static class ServerHolder {
        @NonNull final MtpServer server;
        @NonNull final MtpDatabase database;

        ServerHolder(@NonNull MtpServer server, @NonNull MtpDatabase database) {
            Preconditions.checkNotNull(server);
            Preconditions.checkNotNull(database);
            this.server = server;
            this.database = database;
        }

        void close() {
            this.database.setServer(null);
        }
    }

    private class OnServerTerminated implements Runnable {
        @Override
        public void run() {
            synchronized (MtpService.class) {
                if (sServerHolder == null) {
                    Log.e(TAG, "sServerHolder is unexpectedly null.");
                    return;
                }
                sServerHolder.close();
                sServerHolder = null;
            }
        }
    }
}
