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

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecordingConfiguration;
import android.media.AudioSystem;
import android.media.IRecordingConfigDispatcher;
import android.media.MediaRecorder;
import android.media.audiofx.AudioEffect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * Class to receive and dispatch updates from AudioSystem about recording configurations.
 */
public final class RecordingActivityMonitor implements AudioSystem.AudioRecordingCallback {

    public final static String TAG = "AudioService.RecordingActivityMonitor";

    private ArrayList<RecMonitorClient> mClients = new ArrayList<RecMonitorClient>();
    // a public client is one that needs an anonymized version of the playback configurations, we
    // keep track of whether there is at least one to know when we need to create the list of
    // playback configurations that do not contain uid/package name information.
    private boolean mHasPublicClients = false;

    static final class RecordingState {
        private final int mRiid;
        private final RecorderDeathHandler mDeathHandler;
        private boolean mIsActive;
        private AudioRecordingConfiguration mConfig;

        RecordingState(int riid, RecorderDeathHandler handler) {
            mRiid = riid;
            mDeathHandler = handler;
        }

        RecordingState(AudioRecordingConfiguration config) {
            mRiid = AudioManager.RECORD_RIID_INVALID;
            mDeathHandler = null;
            mConfig = config;
        }

        int getRiid() {
            return mRiid;
        }

        int getPortId() {
            return mConfig != null ? mConfig.getClientPortId() : -1;
        }

        AudioRecordingConfiguration getConfig() {
            return mConfig;
        }

        boolean hasDeathHandler() {
            return mDeathHandler != null;
        }

        boolean isActiveConfiguration() {
            return mIsActive && mConfig != null;
        }

        // returns true if status of an active recording has changed
        boolean setActive(boolean active) {
            if (mIsActive == active) return false;
            mIsActive = active;
            return mConfig != null;
        }

        // returns true if an active recording has been updated
        boolean setConfig(AudioRecordingConfiguration config) {
            if (config.equals(mConfig)) return false;
            mConfig = config;
            return mIsActive;
        }

        void dump(PrintWriter pw) {
            pw.println("riid " + mRiid + "; active? " + mIsActive);
            if (mConfig != null) {
                mConfig.dump(pw);
            } else {
                pw.println("  no config");
            }
        }
    }
    private List<RecordingState> mRecordStates = new ArrayList<RecordingState>();

    private final PackageManager mPackMan;

    RecordingActivityMonitor(Context ctxt) {
        RecMonitorClient.sMonitor = this;
        RecorderDeathHandler.sMonitor = this;
        mPackMan = ctxt.getPackageManager();
    }

    /**
     * Implementation of android.media.AudioSystem.AudioRecordingCallback
     */
    public void onRecordingConfigurationChanged(int event, int riid, int uid, int session,
                                                int source, int portId, boolean silenced,
                                                int[] recordingInfo,
                                                AudioEffect.Descriptor[] clientEffects,
                                                AudioEffect.Descriptor[] effects,
                                                int activeSource, String packName) {
        final AudioRecordingConfiguration config = createRecordingConfiguration(
                uid, session, source, recordingInfo,
                portId, silenced, activeSource, clientEffects, effects);
        if (MediaRecorder.isSystemOnlyAudioSource(source)) {
            // still want to log event, it just won't appear in recording configurations;
            sEventLogger.log(new RecordingEvent(event, riid, config).printLog(TAG));
            return;
        }
        dispatchCallbacks(updateSnapshot(event, riid, config));
    }

    /**
     * Track a recorder provided by the client
     */
    public int trackRecorder(IBinder recorder) {
        if (recorder == null) {
            Log.e(TAG, "trackRecorder called with null token");
            return AudioManager.RECORD_RIID_INVALID;
        }
        final int newRiid = AudioSystem.newAudioRecorderId();
        RecorderDeathHandler handler = new RecorderDeathHandler(newRiid, recorder);
        if (!handler.init()) {
            // probably means that the AudioRecord has already died
            return AudioManager.RECORD_RIID_INVALID;
        }
        synchronized (mRecordStates) {
            mRecordStates.add(new RecordingState(newRiid, handler));
        }
        // a newly added record is inactive, no change in active configs is possible.
        return newRiid;
    }

    /**
     * Receive an event from the client about a tracked recorder
     */
    public void recorderEvent(int riid, int event) {
        int configEvent = event == AudioManager.RECORDER_STATE_STARTED
                ? AudioManager.RECORD_CONFIG_EVENT_START :
                event == AudioManager.RECORDER_STATE_STOPPED
                ? AudioManager.RECORD_CONFIG_EVENT_STOP : AudioManager.RECORD_CONFIG_EVENT_NONE;
        if (riid == AudioManager.RECORD_RIID_INVALID
                || configEvent == AudioManager.RECORD_CONFIG_EVENT_NONE) {
            sEventLogger.log(new RecordingEvent(event, riid, null).printLog(TAG));
            return;
        }
        dispatchCallbacks(updateSnapshot(configEvent, riid, null));
    }

    void unregisterRecorder(int riid) {
        dispatchCallbacks(updateSnapshot(AudioManager.RECORD_CONFIG_EVENT_DEATH, riid, null));
    }

    private void dispatchCallbacks(List<AudioRecordingConfiguration> configs) {
        if (configs == null) { // null means "no changes"
            return;
        }
        synchronized (mClients) {
            // list of recording configurations for "public consumption". It is only computed if
            // there are non-system recording activity listeners.
            final List<AudioRecordingConfiguration> configsPublic = mHasPublicClients
                    ? anonymizeForPublicConsumption(configs) :
                      new ArrayList<AudioRecordingConfiguration>();
            for (RecMonitorClient rmc : mClients) {
                try {
                    if (rmc.mIsPrivileged) {
                        rmc.mDispatcherCb.dispatchRecordingConfigChange(configs);
                    } else {
                        rmc.mDispatcherCb.dispatchRecordingConfigChange(configsPublic);
                    }
                } catch (RemoteException e) {
                    Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
                }
            }
        }
    }

    protected void dump(PrintWriter pw) {
        // recorders
        pw.println("\nRecordActivityMonitor dump time: "
                + DateFormat.getTimeInstance().format(new Date()));
        synchronized (mRecordStates) {
            for (RecordingState state : mRecordStates) {
                state.dump(pw);
            }
        }
        pw.println("\n");
        // log
        sEventLogger.dump(pw);
    }

    private static ArrayList<AudioRecordingConfiguration> anonymizeForPublicConsumption(
            List<AudioRecordingConfiguration> sysConfigs) {
        ArrayList<AudioRecordingConfiguration> publicConfigs =
                new ArrayList<AudioRecordingConfiguration>();
        // only add active anonymized configurations,
        for (AudioRecordingConfiguration config : sysConfigs) {
            publicConfigs.add(AudioRecordingConfiguration.anonymizedCopy(config));
        }
        return publicConfigs;
    }

    void initMonitor() {
        AudioSystem.setRecordingCallback(this);
    }

    void onAudioServerDied() {
        // Remove all RecordingState entries that do not have a death handler (that means
        // they are tracked by the Audio Server). If there were active entries among removed,
        // dispatch active configuration changes.
        List<AudioRecordingConfiguration> configs = null;
        synchronized (mRecordStates) {
            boolean configChanged = false;
            for (Iterator<RecordingState> it = mRecordStates.iterator(); it.hasNext(); ) {
                RecordingState state = it.next();
                if (!state.hasDeathHandler()) {
                    if (state.isActiveConfiguration()) {
                        configChanged = true;
                        sEventLogger.log(new RecordingEvent(
                                        AudioManager.RECORD_CONFIG_EVENT_DEATH,
                                        state.getRiid(), state.getConfig()));
                    }
                    it.remove();
                }
            }
            if (configChanged) {
                configs = getActiveRecordingConfigurations(true /*isPrivileged*/);
            }
        }
        dispatchCallbacks(configs);
    }

    void registerRecordingCallback(IRecordingConfigDispatcher rcdb, boolean isPrivileged) {
        if (rcdb == null) {
            return;
        }
        synchronized (mClients) {
            final RecMonitorClient rmc = new RecMonitorClient(rcdb, isPrivileged);
            if (rmc.init()) {
                if (!isPrivileged) {
                    mHasPublicClients = true;
                }
                mClients.add(rmc);
            }
        }
    }

    void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
        if (rcdb == null) {
            return;
        }
        synchronized (mClients) {
            final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
            boolean hasPublicClients = false;
            while (clientIterator.hasNext()) {
                RecMonitorClient rmc = clientIterator.next();
                if (rcdb.equals(rmc.mDispatcherCb)) {
                    rmc.release();
                    clientIterator.remove();
                } else {
                    if (!rmc.mIsPrivileged) {
                        hasPublicClients = true;
                    }
                }
            }
            mHasPublicClients = hasPublicClients;
        }
    }

    List<AudioRecordingConfiguration> getActiveRecordingConfigurations(boolean isPrivileged) {
        List<AudioRecordingConfiguration> configs = new ArrayList<AudioRecordingConfiguration>();
        synchronized (mRecordStates) {
            for (RecordingState state : mRecordStates) {
                if (state.isActiveConfiguration()) {
                    configs.add(state.getConfig());
                }
            }
        }
        // AudioRecordingConfiguration objects never get updated. If config changes,
        // the reference to the config is set in RecordingState.
        if (!isPrivileged) {
            configs = anonymizeForPublicConsumption(configs);
        }
        return configs;
    }

    /**
     * Create a recording configuration from the provided parameters
     * @param uid
     * @param session
     * @param source
     * @param recordingFormat see
     *     {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int,\
     int, int, boolean, int[], AudioEffect.Descriptor[], AudioEffect.Descriptor[], int, String)}
     *     for the definition of the contents of the array
     * @param portId
     * @param silenced
     * @param activeSource
     * @param clientEffects
     * @param effects
     * @return null a configuration object.
     */
    private AudioRecordingConfiguration createRecordingConfiguration(int uid,
            int session, int source, int[] recordingInfo, int portId, boolean silenced,
            int activeSource, AudioEffect.Descriptor[] clientEffects,
            AudioEffect.Descriptor[] effects) {
        final AudioFormat clientFormat = new AudioFormat.Builder()
                .setEncoding(recordingInfo[0])
                // FIXME this doesn't support index-based masks
                .setChannelMask(recordingInfo[1])
                .setSampleRate(recordingInfo[2])
                .build();
        final AudioFormat deviceFormat = new AudioFormat.Builder()
                .setEncoding(recordingInfo[3])
                // FIXME this doesn't support index-based masks
                .setChannelMask(recordingInfo[4])
                .setSampleRate(recordingInfo[5])
                .build();
        final int patchHandle = recordingInfo[6];
        final String[] packages = mPackMan.getPackagesForUid(uid);
        final String packageName;
        if (packages != null && packages.length > 0) {
            packageName = packages[0];
        } else {
            packageName = "";
        }
        return new AudioRecordingConfiguration(uid, session, source,
                clientFormat, deviceFormat, patchHandle, packageName,
                portId, silenced, activeSource, clientEffects, effects);
    }

    /**
     * Update the internal "view" of the active recording sessions
     * @param event RECORD_CONFIG_EVENT_...
     * @param riid
     * @param config
     * @return null if the list of active recording sessions has not been modified, a list
     *     with the current active configurations otherwise.
     */
    private List<AudioRecordingConfiguration> updateSnapshot(
            int event, int riid, AudioRecordingConfiguration config) {
        List<AudioRecordingConfiguration> configs = null;
        synchronized (mRecordStates) {
            int stateIndex = -1;
            if (riid != AudioManager.RECORD_RIID_INVALID) {
                stateIndex = findStateByRiid(riid);
            } else if (config != null) {
                stateIndex = findStateByPortId(config.getClientPortId());
            }
            if (stateIndex == -1) {
                if (event == AudioManager.RECORD_CONFIG_EVENT_START && config != null) {
                    // First time registration for a recorder tracked by AudioServer.
                    mRecordStates.add(new RecordingState(config));
                    stateIndex = mRecordStates.size() - 1;
                } else {
                    if (config == null) {
                        // Records tracked by clients must be registered first via trackRecorder.
                        Log.e(TAG, String.format(
                                        "Unexpected event %d for riid %d", event, riid));
                    }
                    return configs;
                }
            }
            final RecordingState state = mRecordStates.get(stateIndex);

            boolean configChanged;
            switch (event) {
                case AudioManager.RECORD_CONFIG_EVENT_START:
                    configChanged = state.setActive(true);
                    if (config != null) { // ??? Can remove ???
                        configChanged = state.setConfig(config) || configChanged;
                    }
                    break;
                case AudioManager.RECORD_CONFIG_EVENT_UPDATE:
                    // For this event config != null
                    configChanged = state.setConfig(config);
                    break;
                case AudioManager.RECORD_CONFIG_EVENT_STOP:
                    configChanged = state.setActive(false);
                    if (!state.hasDeathHandler()) {
                        // A recorder tracked by AudioServer has to be removed now so it
                        // does not leak. It will be re-registered if recording starts again.
                        mRecordStates.remove(stateIndex);
                    }
                    break;
                case AudioManager.RECORD_CONFIG_EVENT_DEATH:
                    configChanged = state.isActiveConfiguration();
                    mRecordStates.remove(stateIndex);
                    break;
                default:
                    Log.e(TAG, String.format("Unknown event %d for riid %d / portid %d",
                                    event, riid, state.getPortId()));
                    configChanged = false;
            }
            if (configChanged) {
                sEventLogger.log(new RecordingEvent(event, riid, state.getConfig()));
                configs = getActiveRecordingConfigurations(true /*isPrivileged*/);
            }
        }
        return configs;
    }

    // riid is assumed to be valid
    private int findStateByRiid(int riid) {
        synchronized (mRecordStates) {
            for (int i = 0; i < mRecordStates.size(); i++) {
                if (mRecordStates.get(i).getRiid() == riid) {
                    return i;
                }
            }
        }
        return -1;
    }

    private int findStateByPortId(int portId) {
        // Lookup by portId is unambiguous only for recordings managed by the Audio Server.
        synchronized (mRecordStates) {
            for (int i = 0; i < mRecordStates.size(); i++) {
                if (!mRecordStates.get(i).hasDeathHandler()
                        && mRecordStates.get(i).getPortId() == portId) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * Inner class to track clients that want to be notified of recording updates
     */
    private final static class RecMonitorClient implements IBinder.DeathRecipient {

        // can afford to be static because only one RecordingActivityMonitor ever instantiated
        static RecordingActivityMonitor sMonitor;

        final IRecordingConfigDispatcher mDispatcherCb;
        final boolean mIsPrivileged;

        RecMonitorClient(IRecordingConfigDispatcher rcdb, boolean isPrivileged) {
            mDispatcherCb = rcdb;
            mIsPrivileged = isPrivileged;
        }

        public void binderDied() {
            Log.w(TAG, "client died");
            sMonitor.unregisterRecordingCallback(mDispatcherCb);
        }

        boolean init() {
            try {
                mDispatcherCb.asBinder().linkToDeath(this, 0);
                return true;
            } catch (RemoteException e) {
                Log.w(TAG, "Could not link to client death", e);
                return false;
            }
        }

        void release() {
            mDispatcherCb.asBinder().unlinkToDeath(this, 0);
        }
    }

    private static final class RecorderDeathHandler implements IBinder.DeathRecipient {

        // can afford to be static because only one RecordingActivityMonitor ever instantiated
        static RecordingActivityMonitor sMonitor;

        final int mRiid;
        private final IBinder mRecorderToken;

        RecorderDeathHandler(int riid, IBinder recorderToken) {
            mRiid = riid;
            mRecorderToken = recorderToken;
        }

        public void binderDied() {
            sMonitor.unregisterRecorder(mRiid);
        }

        boolean init() {
            try {
                mRecorderToken.linkToDeath(this, 0);
                return true;
            } catch (RemoteException e) {
                Log.w(TAG, "Could not link to recorder death", e);
                return false;
            }
        }
    }

    /**
     * Inner class for recording event logging
     */
    private static final class RecordingEvent extends AudioEventLogger.Event {
        private final int mRecEvent;
        private final int mRIId;
        private final int mClientUid;
        private final int mSession;
        private final int mSource;
        private final String mPackName;

        RecordingEvent(int event, int riid, AudioRecordingConfiguration config) {
            mRecEvent = event;
            mRIId = riid;
            if (config != null) {
                mClientUid = config.getClientUid();
                mSession = config.getClientAudioSessionId();
                mSource = config.getClientAudioSource();
                mPackName = config.getClientPackageName();
            } else {
                mClientUid = -1;
                mSession = -1;
                mSource = -1;
                mPackName = null;
            }
        }

        private static String recordEventToString(int recEvent) {
            switch (recEvent) {
                case AudioManager.RECORD_CONFIG_EVENT_START:
                    return "start";
                case AudioManager.RECORD_CONFIG_EVENT_UPDATE:
                    return "update";
                case AudioManager.RECORD_CONFIG_EVENT_STOP:
                    return "stop";
                case AudioManager.RECORD_CONFIG_EVENT_DEATH:
                    return "death";
                default:
                    return "unknown (" + recEvent + ")";
            }
        }

        @Override
        public String eventToString() {
            return new StringBuilder("rec ").append(recordEventToString(mRecEvent))
                    .append(" riid:").append(mRIId)
                    .append(" uid:").append(mClientUid)
                    .append(" session:").append(mSession)
                    .append(" src:").append(MediaRecorder.toLogFriendlyAudioSource(mSource))
                    .append(mPackName == null ? "" : " pack:" + mPackName).toString();
        }
    }

    private static final AudioEventLogger sEventLogger = new AudioEventLogger(50,
            "recording activity received by AudioService");
}
