/*
 * Copyright (C) 2012 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.dreams;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.IBinder.DeathRecipient;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamService;
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;

import java.io.PrintWriter;
import java.util.NoSuchElementException;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;

/**
 * Internal controller for starting and stopping the current dream and managing related state.
 *
 * Assumes all operations are called from the dream handler thread.
 */
final class DreamController {
    private static final String TAG = "DreamController";

    // How long we wait for a newly bound dream to create the service connection
    private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000;

    // Time to allow the dream to perform an exit transition when waking up.
    private static final int DREAM_FINISH_TIMEOUT = 5 * 1000;

    private final Context mContext;
    private final Handler mHandler;
    private final Listener mListener;
    private final IWindowManager mIWindowManager;
    private long mDreamStartTime;

    private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    private final Intent mDreamingStoppedIntent = new Intent(Intent.ACTION_DREAMING_STOPPED)
            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

    private final Intent mCloseNotificationShadeIntent;

    private DreamRecord mCurrentDream;

    private final Runnable mStopUnconnectedDreamRunnable = new Runnable() {
        @Override
        public void run() {
            if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) {
                Slog.w(TAG, "Bound dream did not connect in the time allotted");
                stopDream(true /*immediate*/);
            }
        }
    };

    private final Runnable mStopStubbornDreamRunnable = new Runnable() {
        @Override
        public void run() {
            Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted");
            stopDream(true /*immediate*/);
        }
    };

    public DreamController(Context context, Handler handler, Listener listener) {
        mContext = context;
        mHandler = handler;
        mListener = listener;
        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
        mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        mCloseNotificationShadeIntent.putExtra("reason", "dream");
    }

    public void dump(PrintWriter pw) {
        pw.println("Dreamland:");
        if (mCurrentDream != null) {
            pw.println("  mCurrentDream:");
            pw.println("    mToken=" + mCurrentDream.mToken);
            pw.println("    mName=" + mCurrentDream.mName);
            pw.println("    mIsTest=" + mCurrentDream.mIsTest);
            pw.println("    mCanDoze=" + mCurrentDream.mCanDoze);
            pw.println("    mUserId=" + mCurrentDream.mUserId);
            pw.println("    mBound=" + mCurrentDream.mBound);
            pw.println("    mService=" + mCurrentDream.mService);
            pw.println("    mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast);
            pw.println("    mWakingGently=" + mCurrentDream.mWakingGently);
        } else {
            pw.println("  mCurrentDream: null");
        }
    }

    public void startDream(Binder token, ComponentName name,
            boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
        stopDream(true /*immediate*/);

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
        try {
            // Close the notification shade. No need to send to all, but better to be explicit.
            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL);

            Slog.i(TAG, "Starting dream: name=" + name
                    + ", isTest=" + isTest + ", canDoze=" + canDoze
                    + ", userId=" + userId);

            mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId, wakeLock);

            mDreamStartTime = SystemClock.elapsedRealtime();
            MetricsLogger.visible(mContext,
                    mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);

            try {
                mIWindowManager.addWindowToken(token, TYPE_DREAM, DEFAULT_DISPLAY);
            } catch (RemoteException ex) {
                Slog.e(TAG, "Unable to add window token for dream.", ex);
                stopDream(true /*immediate*/);
                return;
            }

            Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
            intent.setComponent(name);
            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            try {
                if (!mContext.bindServiceAsUser(intent, mCurrentDream,
                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                        new UserHandle(userId))) {
                    Slog.e(TAG, "Unable to bind dream service: " + intent);
                    stopDream(true /*immediate*/);
                    return;
                }
            } catch (SecurityException ex) {
                Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
                stopDream(true /*immediate*/);
                return;
            }

            mCurrentDream.mBound = true;
            mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }

    public void stopDream(boolean immediate) {
        if (mCurrentDream == null) {
            return;
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "stopDream");
        try {
            if (!immediate) {
                if (mCurrentDream.mWakingGently) {
                    return; // already waking gently
                }

                if (mCurrentDream.mService != null) {
                    // Give the dream a moment to wake up and finish itself gently.
                    mCurrentDream.mWakingGently = true;
                    try {
                        mCurrentDream.mService.wakeUp();
                        mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT);
                        return;
                    } catch (RemoteException ex) {
                        // oh well, we tried, finish immediately instead
                    }
                }
            }

            final DreamRecord oldDream = mCurrentDream;
            mCurrentDream = null;
            Slog.i(TAG, "Stopping dream: name=" + oldDream.mName
                    + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
                    + ", userId=" + oldDream.mUserId);
            MetricsLogger.hidden(mContext,
                    oldDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
            MetricsLogger.histogram(mContext,
                    oldDream.mCanDoze ? "dozing_minutes" : "dreaming_minutes" ,
                    (int) ((SystemClock.elapsedRealtime() - mDreamStartTime) / (1000L * 60L)));

            mHandler.removeCallbacks(mStopUnconnectedDreamRunnable);
            mHandler.removeCallbacks(mStopStubbornDreamRunnable);

            if (oldDream.mSentStartBroadcast) {
                mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL);
            }

            if (oldDream.mService != null) {
                // Tell the dream that it's being stopped so that
                // it can shut down nicely before we yank its window token out from
                // under it.
                try {
                    oldDream.mService.detach();
                } catch (RemoteException ex) {
                    // we don't care; this thing is on the way out
                }

                try {
                    oldDream.mService.asBinder().unlinkToDeath(oldDream, 0);
                } catch (NoSuchElementException ex) {
                    // don't care
                }
                oldDream.mService = null;
            }

            if (oldDream.mBound) {
                mContext.unbindService(oldDream);
            }
            oldDream.releaseWakeLockIfNeeded();

            try {
                mIWindowManager.removeWindowToken(oldDream.mToken, DEFAULT_DISPLAY);
            } catch (RemoteException ex) {
                Slog.w(TAG, "Error removing window token for dream.", ex);
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mListener.onDreamStopped(oldDream.mToken);
                }
            });
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }

    private void attach(IDreamService service) {
        try {
            service.asBinder().linkToDeath(mCurrentDream, 0);
            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
                    mCurrentDream.mDreamingStartedCallback);
        } catch (RemoteException ex) {
            Slog.e(TAG, "The dream service died unexpectedly.", ex);
            stopDream(true /*immediate*/);
            return;
        }

        mCurrentDream.mService = service;

        if (!mCurrentDream.mIsTest) {
            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL);
            mCurrentDream.mSentStartBroadcast = true;
        }
    }

    /**
     * Callback interface to be implemented by the {@link DreamManagerService}.
     */
    public interface Listener {
        void onDreamStopped(Binder token);
    }

    private final class DreamRecord implements DeathRecipient, ServiceConnection {
        public final Binder mToken;
        public final ComponentName mName;
        public final boolean mIsTest;
        public final boolean mCanDoze;
        public final int mUserId;

        public PowerManager.WakeLock mWakeLock;
        public boolean mBound;
        public boolean mConnected;
        public IDreamService mService;
        public boolean mSentStartBroadcast;

        public boolean mWakingGently;

        public DreamRecord(Binder token, ComponentName name,
                boolean isTest, boolean canDoze, int userId, PowerManager.WakeLock wakeLock) {
            mToken = token;
            mName = name;
            mIsTest = isTest;
            mCanDoze = canDoze;
            mUserId  = userId;
            mWakeLock = wakeLock;
            // Hold the lock while we're waiting for the service to connect and start dreaming.
            // Released after the service has started dreaming, we stop dreaming, or it timed out.
            mWakeLock.acquire();
            mHandler.postDelayed(mReleaseWakeLockIfNeeded, 10000);
        }

        // May be called on any thread.
        @Override
        public void binderDied() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mService = null;
                    if (mCurrentDream == DreamRecord.this) {
                        stopDream(true /*immediate*/);
                    }
                }
            });
        }

        // May be called on any thread.
        @Override
        public void onServiceConnected(ComponentName name, final IBinder service) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mConnected = true;
                    if (mCurrentDream == DreamRecord.this && mService == null) {
                        attach(IDreamService.Stub.asInterface(service));
                        // Wake lock will be released once dreaming starts.
                    } else {
                        releaseWakeLockIfNeeded();
                    }
                }
            });
        }

        // May be called on any thread.
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mService = null;
                    if (mCurrentDream == DreamRecord.this) {
                        stopDream(true /*immediate*/);
                    }
                }
            });
        }

        void releaseWakeLockIfNeeded() {
            if (mWakeLock != null) {
                mWakeLock.release();
                mWakeLock = null;
                mHandler.removeCallbacks(mReleaseWakeLockIfNeeded);
            }
        }

        final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;

        final IRemoteCallback mDreamingStartedCallback = new IRemoteCallback.Stub() {
            // May be called on any thread.
            @Override
            public void sendResult(Bundle data) throws RemoteException {
                mHandler.post(mReleaseWakeLockIfNeeded);
            }
        };
    }
}