/*
 * Copyright (C) 2015 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;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.IBinder;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import android.view.IGraphicsStats;
import android.view.ThreadedRenderer;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * This service's job is to collect aggregate rendering profile data. It
 * does this by allowing rendering processes to request an ashmem buffer
 * to place their stats into. This buffer will be pre-initialized with historical
 * data for that process if it exists (if the userId & packageName match a buffer
 * in the historical log)
 *
 * This service does not itself attempt to understand the data in the buffer,
 * its primary job is merely to manage distributing these buffers. However,
 * it is assumed that this buffer is for ThreadedRenderer and delegates
 * directly to ThreadedRenderer for dumping buffers.
 *
 * MEMORY USAGE:
 *
 * This class consumes UP TO:
 * 1) [active rendering processes] * (ASHMEM_SIZE * 2)
 * 2) ASHMEM_SIZE (for scratch space used during dumping)
 * 3) ASHMEM_SIZE * HISTORY_SIZE
 *
 * Currently ASHMEM_SIZE is 256 bytes and HISTORY_SIZE is 20. Assuming
 * the system then also has 10 active rendering processes in the worst case
 * this would end up using under 14KiB (12KiB for the buffers, plus some overhead
 * for userId, pid, package name, and a couple other objects)
 *
 *  @hide */
public class GraphicsStatsService extends IGraphicsStats.Stub {
    public static final String GRAPHICS_STATS_SERVICE = "graphicsstats";

    private static final String TAG = "GraphicsStatsService";
    private static final int ASHMEM_SIZE = 256;
    private static final int HISTORY_SIZE = 20;

    private final Context mContext;
    private final Object mLock = new Object();
    private ArrayList<ActiveBuffer> mActive = new ArrayList<>();
    private HistoricalData[] mHistoricalLog = new HistoricalData[HISTORY_SIZE];
    private int mNextHistoricalSlot = 0;
    private byte[] mTempBuffer = new byte[ASHMEM_SIZE];

    public GraphicsStatsService(Context context) {
        mContext = context;
    }

    private boolean isValid(int uid, String packageName) {
        try {
            PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
            return info.applicationInfo.uid == uid;
        } catch (NameNotFoundException e) {
        }
        return false;
    }

    @Override
    public ParcelFileDescriptor requestBufferForProcess(String packageName, IBinder token)
            throws RemoteException {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        ParcelFileDescriptor pfd = null;
        long callingIdentity = Binder.clearCallingIdentity();
        try {
            if (!isValid(uid, packageName)) {
                throw new RemoteException("Invalid package name");
            }
            synchronized (mLock) {
                pfd = requestBufferForProcessLocked(token, uid, pid, packageName);
            }
        } finally {
            Binder.restoreCallingIdentity(callingIdentity);
        }
        return pfd;
    }

    private ParcelFileDescriptor getPfd(MemoryFile file) {
        try {
            return new ParcelFileDescriptor(file.getFileDescriptor());
        } catch (IOException ex) {
            throw new IllegalStateException("Failed to get PFD from memory file", ex);
        }
    }

    private ParcelFileDescriptor requestBufferForProcessLocked(IBinder token,
            int uid, int pid, String packageName) throws RemoteException {
        ActiveBuffer buffer = fetchActiveBuffersLocked(token, uid, pid, packageName);
        return getPfd(buffer.mProcessBuffer);
    }

    private void processDied(ActiveBuffer buffer) {
        synchronized (mLock) {
            mActive.remove(buffer);
            Log.d("GraphicsStats", "Buffer count: " + mActive.size());
        }
        HistoricalData data = buffer.mPreviousData;
        buffer.mPreviousData = null;
        if (data == null) {
            data = mHistoricalLog[mNextHistoricalSlot];
            if (data == null) {
                data = new HistoricalData();
            }
        }
        data.update(buffer.mPackageName, buffer.mUid, buffer.mProcessBuffer);
        buffer.closeAllBuffers();

        mHistoricalLog[mNextHistoricalSlot] = data;
        mNextHistoricalSlot = (mNextHistoricalSlot + 1) % mHistoricalLog.length;
    }

    private ActiveBuffer fetchActiveBuffersLocked(IBinder token, int uid, int pid,
            String packageName) throws RemoteException {
        int size = mActive.size();
        for (int i = 0; i < size; i++) {
            ActiveBuffer buffers = mActive.get(i);
            if (buffers.mPid == pid
                    && buffers.mUid == uid) {
                return buffers;
            }
        }
        // Didn't find one, need to create it
        try {
            ActiveBuffer buffers = new ActiveBuffer(token, uid, pid, packageName);
            mActive.add(buffers);
            return buffers;
        } catch (IOException ex) {
            throw new RemoteException("Failed to allocate space");
        }
    }

    private HistoricalData removeHistoricalDataLocked(int uid, String packageName) {
        for (int i = 0; i < mHistoricalLog.length; i++) {
            final HistoricalData data = mHistoricalLog[i];
            if (data != null && data.mUid == uid
                    && data.mPackageName.equals(packageName)) {
                if (i == mNextHistoricalSlot) {
                    mHistoricalLog[i] = null;
                } else {
                    mHistoricalLog[i] = mHistoricalLog[mNextHistoricalSlot];
                    mHistoricalLog[mNextHistoricalSlot] = null;
                }
                return data;
            }
        }
        return null;
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
        synchronized (mLock) {
            for (int i = 0; i < mActive.size(); i++) {
                final ActiveBuffer buffer = mActive.get(i);
                fout.print("Package: ");
                fout.print(buffer.mPackageName);
                fout.flush();
                try {
                    buffer.mProcessBuffer.readBytes(mTempBuffer, 0, 0, ASHMEM_SIZE);
                    ThreadedRenderer.dumpProfileData(mTempBuffer, fd);
                } catch (IOException e) {
                    fout.println("Failed to dump");
                }
                fout.println();
            }
            for (HistoricalData buffer : mHistoricalLog) {
                if (buffer == null) continue;
                fout.print("Package: ");
                fout.print(buffer.mPackageName);
                fout.flush();
                ThreadedRenderer.dumpProfileData(buffer.mBuffer, fd);
                fout.println();
            }
        }
    }

    private final class ActiveBuffer implements DeathRecipient {
        final int mUid;
        final int mPid;
        final String mPackageName;
        final IBinder mToken;
        MemoryFile mProcessBuffer;
        HistoricalData mPreviousData;

        ActiveBuffer(IBinder token, int uid, int pid, String packageName)
                throws RemoteException, IOException {
            mUid = uid;
            mPid = pid;
            mPackageName = packageName;
            mToken = token;
            mToken.linkToDeath(this, 0);
            mProcessBuffer = new MemoryFile("GFXStats-" + uid, ASHMEM_SIZE);
            mPreviousData = removeHistoricalDataLocked(mUid, mPackageName);
            if (mPreviousData != null) {
                mProcessBuffer.writeBytes(mPreviousData.mBuffer, 0, 0, ASHMEM_SIZE);
            }
        }

        @Override
        public void binderDied() {
            mToken.unlinkToDeath(this, 0);
            processDied(this);
        }

        void closeAllBuffers() {
            if (mProcessBuffer != null) {
                mProcessBuffer.close();
                mProcessBuffer = null;
            }
        }
    }

    private final static class HistoricalData {
        final byte[] mBuffer = new byte[ASHMEM_SIZE];
        int mUid;
        String mPackageName;

        void update(String packageName, int uid, MemoryFile file) {
            mUid = uid;
            mPackageName = packageName;
            try {
                file.readBytes(mBuffer, 0, 0, ASHMEM_SIZE);
            } catch (IOException e) {}
        }
    }
}
