/*
 * Copyright (C) 2011 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.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
import android.view.WindowManager;

import java.io.PrintWriter;

class InputConsumerImpl implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    final InputChannel mServerChannel, mClientChannel;
    final InputApplicationHandle mApplicationHandle;
    final InputWindowHandle mWindowHandle;

    final IBinder mToken;
    final String mName;
    final int mClientPid;
    final UserHandle mClientUser;

    final SurfaceControl mInputSurface;
    Rect mTmpClipRect = new Rect();
    private final Rect mTmpRect = new Rect();
    private final Point mOldPosition = new Point();
    private final Rect mOldWindowCrop = new Rect();

    InputConsumerImpl(WindowManagerService service, IBinder token, String name,
            InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) {
        mService = service;
        mToken = token;
        mName = name;
        mClientPid = clientPid;
        mClientUser = clientUser;

        InputChannel[] channels = InputChannel.openInputChannelPair(name);
        mServerChannel = channels[0];
        if (inputChannel != null) {
            channels[1].transferTo(inputChannel);
            channels[1].dispose();
            mClientChannel = inputChannel;
        } else {
            mClientChannel = channels[1];
        }
        mService.mInputManager.registerInputChannel(mServerChannel, null);

        mApplicationHandle = new InputApplicationHandle(new Binder());
        mApplicationHandle.name = name;
        mApplicationHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;

        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId);
        mWindowHandle.name = name;
        mWindowHandle.token = mServerChannel.getToken();
        mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
        mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
        mWindowHandle.layoutParamsFlags = 0;
        mWindowHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
        mWindowHandle.visible = true;
        mWindowHandle.canReceiveKeys = false;
        mWindowHandle.hasFocus = false;
        mWindowHandle.hasWallpaper = false;
        mWindowHandle.paused = false;
        mWindowHandle.ownerPid = Process.myPid();
        mWindowHandle.ownerUid = Process.myUid();
        mWindowHandle.inputFeatures = 0;
        mWindowHandle.scaleFactor = 1.0f;

        mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
                .getSession()).setContainerLayer().setName("Input Consumer " + name)
                .build();
    }

    void linkToDeathRecipient() {
        if (mToken == null) {
            return;
        }

        try {
            mToken.linkToDeath(this, 0);
        } catch (RemoteException e) {
            // Client died, do nothing
        }
    }

    void unlinkFromDeathRecipient() {
        if (mToken == null) {
            return;
        }

        mToken.unlinkToDeath(this, 0);
    }

    void layout(SurfaceControl.Transaction t, int dw, int dh) {
        mTmpRect.set(0, 0, dw, dh);
        layout(t, mTmpRect);
    }

    void layout(SurfaceControl.Transaction t, Rect r) {
        mTmpClipRect.set(0, 0, r.width(), r.height());

        if (mOldPosition.equals(r.left, r.top) && mOldWindowCrop.equals(mTmpClipRect)) {
            return;
        }

        t.setPosition(mInputSurface, r.left, r.top);
        t.setWindowCrop(mInputSurface, mTmpClipRect);

        mOldPosition.set(r.left, r.top);
        mOldWindowCrop.set(mTmpClipRect);
    }

    void hide(SurfaceControl.Transaction t) {
        t.hide(mInputSurface);
    }

    void show(SurfaceControl.Transaction t, WindowState w) {
        t.show(mInputSurface);
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1);
    }

    void show(SurfaceControl.Transaction t, int layer) {
        t.show(mInputSurface);
        t.setInputWindowInfo(mInputSurface, mWindowHandle);
        t.setLayer(mInputSurface, layer);
    }

    private int getLayerLw(int windowType) {
        return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
                * WindowManagerService.TYPE_LAYER_MULTIPLIER
                + WindowManagerService.TYPE_LAYER_OFFSET;
    }

    void disposeChannelsLw() {
        mService.mInputManager.unregisterInputChannel(mServerChannel);
        mClientChannel.dispose();
        mServerChannel.dispose();
        unlinkFromDeathRecipient();
    }

    @Override
    public void binderDied() {
        synchronized (mService.getWindowManagerLock()) {
            // Clean up the input consumer
            final InputMonitor inputMonitor =
                    mService.mRoot.getDisplayContent(mWindowHandle.displayId).getInputMonitor();
            inputMonitor.destroyInputConsumer(mName);
            unlinkFromDeathRecipient();
        }
    }

    void dump(PrintWriter pw, String name, String prefix) {
        pw.println(prefix + "  name=" + name + " pid=" + mClientPid + " user=" + mClientUser);
    }
}
