/*
 * 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.app.AlarmManager;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.MemoryFile;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
import android.view.IGraphicsStats;
import android.view.IGraphicsStatsCallback;

import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.TimeZone;

/**
 * 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.
 *
 * Buffers are rotated on a daily (in UTC) basis and only the 3 most-recent days
 * are kept.
 *
 * The primary consumer of this is incident reports and automated metric checking. It is not
 * intended for end-developer consumption, for that we have gfxinfo.
 *
 * Buffer rotation process:
 * 1) Alarm fires
 * 2) onRotateGraphicsStatsBuffer() is sent to all active processes
 * 3) Upon receiving the callback, the process will stop using the previous ashmem buffer and
 *    request a new one.
 * 4) When that request is received we now know that the ashmem region is no longer in use so
 *    it gets queued up for saving to disk and a new ashmem region is created and returned
 *    for the process to use.
 *
 *  @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 SAVE_BUFFER = 1;
    private static final int DELETE_OLD = 2;

    private static final int AID_STATSD = 1066; // Statsd uid is set to 1066 forever.

    // This isn't static because we need this to happen after registerNativeMethods, however
    // the class is loaded (and thus static ctor happens) before that occurs.
    private final int ASHMEM_SIZE = nGetAshmemSize();
    private final byte[] ZERO_DATA = new byte[ASHMEM_SIZE];

    private final Context mContext;
    private final AppOpsManager mAppOps;
    private final AlarmManager mAlarmManager;
    private final Object mLock = new Object();
    private ArrayList<ActiveBuffer> mActive = new ArrayList<>();
    private File mGraphicsStatsDir;
    private final Object mFileAccessLock = new Object();
    private Handler mWriteOutHandler;
    private boolean mRotateIsScheduled = false;

    public GraphicsStatsService(Context context) {
        mContext = context;
        mAppOps = context.getSystemService(AppOpsManager.class);
        mAlarmManager = context.getSystemService(AlarmManager.class);
        File systemDataDir = new File(Environment.getDataDirectory(), "system");
        mGraphicsStatsDir = new File(systemDataDir, "graphicsstats");
        mGraphicsStatsDir.mkdirs();
        if (!mGraphicsStatsDir.exists()) {
            throw new IllegalStateException("Graphics stats directory does not exist: "
                    + mGraphicsStatsDir.getAbsolutePath());
        }
        HandlerThread bgthread = new HandlerThread("GraphicsStats-disk", Process.THREAD_PRIORITY_BACKGROUND);
        bgthread.start();

        mWriteOutHandler = new Handler(bgthread.getLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                switch (msg.what) {
                    case SAVE_BUFFER:
                        saveBuffer((HistoricalBuffer) msg.obj);
                        break;
                    case DELETE_OLD:
                        deleteOldBuffers();
                        break;
                }
                return true;
            }
        });
        nativeInit();
    }

    /**
     * Current rotation policy is to rotate at midnight UTC. We don't specify RTC_WAKEUP because
     * rotation can be delayed if there's otherwise no activity. However exact is used because
     * we don't want the system to delay it by TOO much.
     */
    private void scheduleRotateLocked() {
        if (mRotateIsScheduled) {
            return;
        }
        mRotateIsScheduled = true;
        Calendar calendar = normalizeDate(System.currentTimeMillis());
        calendar.add(Calendar.DATE, 1);
        mAlarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), TAG, this::onAlarm,
                mWriteOutHandler);
    }

    private void onAlarm() {
        // We need to make a copy since some of the callbacks won't be proxy and thus
        // can result in a re-entrant acquisition of mLock that would result in a modification
        // of mActive during iteration.
        ActiveBuffer[] activeCopy;
        synchronized (mLock) {
            mRotateIsScheduled = false;
            scheduleRotateLocked();
            activeCopy = mActive.toArray(new ActiveBuffer[0]);
        }
        for (ActiveBuffer active : activeCopy) {
            try {
                active.mCallback.onRotateGraphicsStatsBuffer();
            } catch (RemoteException e) {
                Log.w(TAG, String.format("Failed to notify '%s' (pid=%d) to rotate buffers",
                        active.mInfo.packageName, active.mPid), e);
            }
        }
        // Give a few seconds for everyone to rotate before doing the cleanup
        mWriteOutHandler.sendEmptyMessageDelayed(DELETE_OLD, 10000);
    }

    @Override
    public ParcelFileDescriptor requestBufferForProcess(String packageName, IGraphicsStatsCallback token)
            throws RemoteException {
        int uid = Binder.getCallingUid();
        int pid = Binder.getCallingPid();
        ParcelFileDescriptor pfd = null;
        long callingIdentity = Binder.clearCallingIdentity();
        try {
            mAppOps.checkPackage(uid, packageName);
            PackageInfo info = mContext.getPackageManager().getPackageInfoAsUser(
                    packageName,
                    0,
                    UserHandle.getUserId(uid));
            synchronized (mLock) {
                pfd = requestBufferForProcessLocked(token, uid, pid, packageName,
                        info.getLongVersionCode());
            }
        } catch (PackageManager.NameNotFoundException ex) {
            throw new RemoteException("Unable to find package: '" + packageName + "'");
        } finally {
            Binder.restoreCallingIdentity(callingIdentity);
        }
        return pfd;
    }

    // If lastFullDay is true, pullGraphicsStats returns stats for the last complete day/24h period
    // that does not include today. If lastFullDay is false, pullGraphicsStats returns stats for the
    // current day.
    // This method is invoked from native code only.
    @SuppressWarnings({"UnusedDeclaration"})
    private long pullGraphicsStats(boolean lastFullDay) throws RemoteException {
        int uid = Binder.getCallingUid();

        // DUMP and PACKAGE_USAGE_STATS permissions are required to invoke this method.
        // TODO: remove exception for statsd daemon after required permissions are granted. statsd
        // TODO: should have these permissions granted by data/etc/platform.xml, but it does not.
        if (uid != AID_STATSD) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new FastPrintWriter(sw);
            if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) {
                pw.flush();
                throw new RemoteException(sw.toString());
            }
        }

        long callingIdentity = Binder.clearCallingIdentity();
        try {
            return pullGraphicsStatsImpl(lastFullDay);
        } finally {
            Binder.restoreCallingIdentity(callingIdentity);
        }
    }

    private long pullGraphicsStatsImpl(boolean lastFullDay) {
        long targetDay;
        if (lastFullDay) {
            // Get stats from yesterday. Stats stay constant, because the day is over.
            targetDay = normalizeDate(System.currentTimeMillis() - 86400000).getTimeInMillis();
        } else {
            // Get stats from today. Stats may change as more apps are run today.
            targetDay = normalizeDate(System.currentTimeMillis()).getTimeInMillis();
        }

        // Find active buffers for targetDay.
        ArrayList<HistoricalBuffer> buffers;
        synchronized (mLock) {
            buffers = new ArrayList<>(mActive.size());
            for (int i = 0; i < mActive.size(); i++) {
                ActiveBuffer buffer = mActive.get(i);
                if (buffer.mInfo.startTime == targetDay) {
                    try {
                        buffers.add(new HistoricalBuffer(buffer));
                    } catch (IOException ex) {
                        // Ignore
                    }
                }
            }
        }

        // Dump active and historic buffers for targetDay in a serialized
        // GraphicsStatsServiceDumpProto proto.
        long dump = nCreateDump(-1, true);
        try {
            synchronized (mFileAccessLock) {
                HashSet<File> skipList = dumpActiveLocked(dump, buffers);
                buffers.clear();
                String subPath = String.format("%d", targetDay);
                File dateDir = new File(mGraphicsStatsDir, subPath);
                if (dateDir.exists()) {
                    for (File pkg : dateDir.listFiles()) {
                        for (File version : pkg.listFiles()) {
                            File data = new File(version, "total");
                            if (skipList.contains(data)) {
                                continue;
                            }
                            nAddToDump(dump, data.getAbsolutePath());
                        }
                    }
                }
            }
        } finally {
            return nFinishDumpInMemory(dump);
        }
    }

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

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

    private Calendar normalizeDate(long timestamp) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        calendar.setTimeInMillis(timestamp);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    private File pathForApp(BufferInfo info) {
        String subPath = String.format("%d/%s/%d/total",
                normalizeDate(info.startTime).getTimeInMillis(), info.packageName, info.versionCode);
        return new File(mGraphicsStatsDir, subPath);
    }

    private void saveBuffer(HistoricalBuffer buffer) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "saving graphicsstats for " + buffer.mInfo.packageName);
        }
        synchronized (mFileAccessLock) {
            File path = pathForApp(buffer.mInfo);
            File parent = path.getParentFile();
            parent.mkdirs();
            if (!parent.exists()) {
                Log.w(TAG, "Unable to create path: '" + parent.getAbsolutePath() + "'");
                return;
            }
            nSaveBuffer(path.getAbsolutePath(), buffer.mInfo.packageName, buffer.mInfo.versionCode,
                    buffer.mInfo.startTime, buffer.mInfo.endTime, buffer.mData);
        }
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    private void deleteRecursiveLocked(File file) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                deleteRecursiveLocked(child);
            }
        }
        if (!file.delete()) {
            Log.w(TAG, "Failed to delete '" + file.getAbsolutePath() + "'!");
        }
    }

    private void deleteOldBuffers() {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "deleting old graphicsstats buffers");
        synchronized (mFileAccessLock) {
            File[] files = mGraphicsStatsDir.listFiles();
            if (files == null || files.length <= 3) {
                return;
            }
            long[] sortedDates = new long[files.length];
            for (int i = 0; i < files.length; i++) {
                try {
                    sortedDates[i] = Long.parseLong(files[i].getName());
                } catch (NumberFormatException ex) {
                    // Skip unrecognized folders
                }
            }
            if (sortedDates.length <= 3) {
                return;
            }
            Arrays.sort(sortedDates);
            for (int i = 0; i < sortedDates.length - 3; i++) {
                deleteRecursiveLocked(new File(mGraphicsStatsDir, Long.toString(sortedDates[i])));
            }
        }
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    private void addToSaveQueue(ActiveBuffer buffer) {
        try {
            HistoricalBuffer data = new HistoricalBuffer(buffer);
            Message.obtain(mWriteOutHandler, SAVE_BUFFER, data).sendToTarget();
        } catch (IOException e) {
            Log.w(TAG, "Failed to copy graphicsstats from " + buffer.mInfo.packageName, e);
        }
        buffer.closeAllBuffers();
    }

    private void processDied(ActiveBuffer buffer) {
        synchronized (mLock) {
            mActive.remove(buffer);
        }
        addToSaveQueue(buffer);
    }

    private ActiveBuffer fetchActiveBuffersLocked(IGraphicsStatsCallback token, int uid, int pid,
            String packageName, long versionCode) throws RemoteException {
        int size = mActive.size();
        long today = normalizeDate(System.currentTimeMillis()).getTimeInMillis();
        for (int i = 0; i < size; i++) {
            ActiveBuffer buffer = mActive.get(i);
            if (buffer.mPid == pid
                    && buffer.mUid == uid) {
                // If the buffer is too old we remove it and return a new one
                if (buffer.mInfo.startTime < today) {
                    buffer.binderDied();
                    break;
                } else {
                    return buffer;
                }
            }
        }
        // Didn't find one, need to create it
        try {
            ActiveBuffer buffers = new ActiveBuffer(token, uid, pid, packageName, versionCode);
            mActive.add(buffers);
            return buffers;
        } catch (IOException ex) {
            throw new RemoteException("Failed to allocate space");
        }
    }

    private HashSet<File> dumpActiveLocked(long dump, ArrayList<HistoricalBuffer> buffers) {
        HashSet<File> skipFiles = new HashSet<>(buffers.size());
        for (int i = 0; i < buffers.size(); i++) {
            HistoricalBuffer buffer = buffers.get(i);
            File path = pathForApp(buffer.mInfo);
            skipFiles.add(path);
            nAddToDump(dump, path.getAbsolutePath(), buffer.mInfo.packageName,
                    buffer.mInfo.versionCode,  buffer.mInfo.startTime, buffer.mInfo.endTime,
                    buffer.mData);
        }
        return skipFiles;
    }

    private void dumpHistoricalLocked(long dump, HashSet<File> skipFiles) {
        for (File date : mGraphicsStatsDir.listFiles()) {
            for (File pkg : date.listFiles()) {
                for (File version : pkg.listFiles()) {
                    File data = new File(version, "total");
                    if (skipFiles.contains(data)) {
                        continue;
                    }
                    nAddToDump(dump, data.getAbsolutePath());
                }
            }
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, fout)) return;
        boolean dumpProto = false;
        for (String str : args) {
            if ("--proto".equals(str)) {
                dumpProto = true;
                break;
            }
        }
        ArrayList<HistoricalBuffer> buffers;
        synchronized (mLock) {
            buffers = new ArrayList<>(mActive.size());
            for (int i = 0; i < mActive.size(); i++) {
                try {
                    buffers.add(new HistoricalBuffer(mActive.get(i)));
                } catch (IOException ex) {
                    // Ignore
                }
            }
        }
        long dump = nCreateDump(fd.getInt$(), dumpProto);
        try {
            synchronized (mFileAccessLock) {
                HashSet<File> skipList = dumpActiveLocked(dump, buffers);
                buffers.clear();
                dumpHistoricalLocked(dump, skipList);
            }
        } finally {
            nFinishDump(dump);
        }
    }

    @Override
    protected void finalize() throws Throwable {
        nativeDestructor();
    }

    private native void nativeInit();
    private static native void nativeDestructor();

    private static native int nGetAshmemSize();
    private static native long nCreateDump(int outFd, boolean isProto);
    private static native void nAddToDump(long dump, String path, String packageName,
            long versionCode, long startTime, long endTime, byte[] data);
    private static native void nAddToDump(long dump, String path);
    private static native void nFinishDump(long dump);
    private static native long nFinishDumpInMemory(long dump);
    private static native void nSaveBuffer(String path, String packageName, long versionCode,
            long startTime, long endTime, byte[] data);

    private final class BufferInfo {
        final String packageName;
        final long versionCode;
        long startTime;
        long endTime;

        BufferInfo(String packageName, long versionCode, long startTime) {
            this.packageName = packageName;
            this.versionCode = versionCode;
            this.startTime = startTime;
        }
    }

    private final class ActiveBuffer implements DeathRecipient {
        final BufferInfo mInfo;
        final int mUid;
        final int mPid;
        final IGraphicsStatsCallback mCallback;
        final IBinder mToken;
        MemoryFile mProcessBuffer;

        ActiveBuffer(IGraphicsStatsCallback token, int uid, int pid, String packageName,
                long versionCode)
                throws RemoteException, IOException {
            mInfo = new BufferInfo(packageName, versionCode, System.currentTimeMillis());
            mUid = uid;
            mPid = pid;
            mCallback = token;
            mToken = mCallback.asBinder();
            mToken.linkToDeath(this, 0);
            mProcessBuffer = new MemoryFile("GFXStats-" + pid, ASHMEM_SIZE);
            mProcessBuffer.writeBytes(ZERO_DATA, 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 class HistoricalBuffer {
        final BufferInfo mInfo;
        final byte[] mData = new byte[ASHMEM_SIZE];
        HistoricalBuffer(ActiveBuffer active) throws IOException {
            mInfo = active.mInfo;
            mInfo.endTime = System.currentTimeMillis();
            active.mProcessBuffer.readBytes(mData, 0, 0, ASHMEM_SIZE);
        }
    }
}
