/*
 * 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;
        }

        void release() {
            if (mDeathHandler != null) {
                mDeathHandler.release();
            }
        }

        // 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));
    }

    /**
     * Stop tracking the recorder
     */
    public void releaseRecorder(int riid) {
        dispatchCallbacks(updateSnapshot(AudioManager.RECORD_CONFIG_EVENT_RELEASE, 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_RELEASE,
                                        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) {
                        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_RELEASE:
                    configChanged = state.isActiveConfiguration();
                    state.release();
                    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.releaseRecorder(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;
            }
        }

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

    /**
     * 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_RELEASE:
                    return "release";
                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");
}
