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

import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.Parcel;
import android.util.Slog;
import android.view.SurfaceControl;

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.DataOutputStream;

// A surface control subclass which logs events to a FD in binary format.
// This can be used in our CTS tests to enable a pattern similar to mocking
// the surface control.
//
// See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
class RemoteSurfaceTrace extends SurfaceControl {
    static final String TAG = "RemoteSurfaceTrace";

    final FileDescriptor mWriteFd;
    final DataOutputStream mOut;

    final WindowManagerService mService;
    final WindowState mWindow;

    RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
        super(wrapped);

        mWriteFd = fd;
        mOut = new DataOutputStream(new FileOutputStream(fd, false));

        mWindow = window;
        mService = mWindow.mService;
    }

    @Override
    public void setAlpha(float alpha) {
        writeFloatEvent("Alpha", alpha);
        super.setAlpha(alpha);
    }

    @Override
    public void setLayer(int zorder) {
        writeIntEvent("Layer", zorder);
        super.setLayer(zorder);
    }

    @Override
    public void setPosition(float x, float y) {
        writeFloatEvent("Position", x, y);
        super.setPosition(x, y);
    }

    @Override
    public void setGeometryAppliesWithResize() {
        writeEvent("GeometryAppliesWithResize");
        super.setGeometryAppliesWithResize();
    }

    @Override
    public void setSize(int w, int h) {
        writeIntEvent("Size", w, h);
        super.setSize(w, h);
    }

    @Override
    public void setWindowCrop(Rect crop) {
        writeRectEvent("Crop", crop);
        super.setWindowCrop(crop);
    }

    @Override
    public void setFinalCrop(Rect crop) {
        writeRectEvent("FinalCrop", crop);
        super.setFinalCrop(crop);
    }

    @Override
    public void setLayerStack(int layerStack) {
        writeIntEvent("LayerStack", layerStack);
        super.setLayerStack(layerStack);
    }

    @Override
    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
        writeFloatEvent("Matrix", dsdx, dtdx, dsdy, dtdy);
        super.setMatrix(dsdx, dtdx, dsdy, dtdy);
    }

    @Override
    public void hide() {
        writeEvent("Hide");
        super.hide();
    }

    @Override
    public void show() {
        writeEvent("Show");
        super.show();
    }

    private void writeEvent(String tag) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
            writeSigil();
        } catch (Exception e) {
            RemoteEventTrace.logException(e);
            mService.disableSurfaceTrace();
        }
    }

    private void writeIntEvent(String tag, int... values) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
            for (int value: values) {
                mOut.writeInt(value);
            }
            writeSigil();
        } catch (Exception e) {
            RemoteEventTrace.logException(e);
            mService.disableSurfaceTrace();
        }
    }

    private void writeFloatEvent(String tag, float... values) {
        try {
            mOut.writeUTF(tag);
            mOut.writeUTF(mWindow.getWindowTag().toString());
            for (float value: values) {
                mOut.writeFloat(value);
            }
            writeSigil();
        } catch (Exception e) {
            RemoteEventTrace.logException(e);
            mService.disableSurfaceTrace();
        }
    }

    private void writeRectEvent(String tag, Rect value) {
        writeFloatEvent(tag, value.left, value.top, value.right, value.bottom);
    }

    private void writeSigil() throws Exception {
        mOut.write(RemoteEventTrace.sigil, 0, 4);
    }
}
