/*
 * 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 static android.Manifest.permission.BIND_DREAM_SERVICE;

import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
import com.android.server.SystemService;

import android.Manifest;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.text.TextUtils;
import android.util.Slog;
import android.view.Display;

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

import libcore.util.Objects;

/**
 * Service api for managing dreams.
 *
 * @hide
 */
public final class DreamManagerService extends SystemService {
    private static final boolean DEBUG = false;
    private static final String TAG = "DreamManagerService";

    private final Object mLock = new Object();

    private final Context mContext;
    private final DreamHandler mHandler;
    private final DreamController mController;
    private final PowerManager mPowerManager;
    private final PowerManagerInternal mPowerManagerInternal;
    private final PowerManager.WakeLock mDozeWakeLock;

    private Binder mCurrentDreamToken;
    private ComponentName mCurrentDreamName;
    private int mCurrentDreamUserId;
    private boolean mCurrentDreamIsTest;
    private boolean mCurrentDreamCanDoze;
    private boolean mCurrentDreamIsDozing;
    private boolean mCurrentDreamIsWaking;
    private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
    private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;

    public DreamManagerService(Context context) {
        super(context);
        mContext = context;
        mHandler = new DreamHandler(FgThread.get().getLooper());
        mController = new DreamController(context, mHandler, mControllerListener);

        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mPowerManagerInternal = getLocalService(PowerManagerInternal.class);
        mDozeWakeLock = mPowerManager.newWakeLock(PowerManager.DOZE_WAKE_LOCK, TAG);
    }

    @Override
    public void onStart() {
        publishBinderService(DreamService.DREAM_SERVICE, new BinderService());
        publishLocalService(DreamManagerInternal.class, new LocalService());
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
            if (Build.IS_DEBUGGABLE) {
                SystemProperties.addChangeCallback(mSystemPropertiesChanged);
            }
            mContext.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    synchronized (mLock) {
                        stopDreamLocked(false /*immediate*/);
                    }
                }
            }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
        }
    }

    private void dumpInternal(PrintWriter pw) {
        pw.println("DREAM MANAGER (dumpsys dreams)");
        pw.println();
        pw.println("mCurrentDreamToken=" + mCurrentDreamToken);
        pw.println("mCurrentDreamName=" + mCurrentDreamName);
        pw.println("mCurrentDreamUserId=" + mCurrentDreamUserId);
        pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest);
        pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze);
        pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing);
        pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking);
        pw.println("mCurrentDreamDozeScreenState="
                + Display.stateToString(mCurrentDreamDozeScreenState));
        pw.println("mCurrentDreamDozeScreenBrightness=" + mCurrentDreamDozeScreenBrightness);
        pw.println("getDozeComponent()=" + getDozeComponent());
        pw.println();

        DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
            @Override
            public void dump(PrintWriter pw, String prefix) {
                mController.dump(pw);
            }
        }, pw, "", 200);
    }

    private boolean isDreamingInternal() {
        synchronized (mLock) {
            return mCurrentDreamToken != null && !mCurrentDreamIsTest
                    && !mCurrentDreamIsWaking;
        }
    }

    private void requestDreamInternal() {
        // Ask the power manager to nap.  It will eventually call back into
        // startDream() if/when it is appropriate to start dreaming.
        // Because napping could cause the screen to turn off immediately if the dream
        // cannot be started, we keep one eye open and gently poke user activity.
        long time = SystemClock.uptimeMillis();
        mPowerManager.userActivity(time, true /*noChangeLights*/);
        mPowerManager.nap(time);
    }

    private void requestAwakenInternal() {
        // Treat an explicit request to awaken as user activity so that the
        // device doesn't immediately go to sleep if the timeout expired,
        // for example when being undocked.
        long time = SystemClock.uptimeMillis();
        mPowerManager.userActivity(time, false /*noChangeLights*/);
        stopDreamInternal(false /*immediate*/);
    }

    private void finishSelfInternal(IBinder token, boolean immediate) {
        if (DEBUG) {
            Slog.d(TAG, "Dream finished: " + token + ", immediate=" + immediate);
        }

        // Note that a dream finishing and self-terminating is not
        // itself considered user activity.  If the dream is ending because
        // the user interacted with the device then user activity will already
        // have been poked so the device will stay awake a bit longer.
        // If the dream is ending on its own for other reasons and no wake
        // locks are held and the user activity timeout has expired then the
        // device may simply go to sleep.
        synchronized (mLock) {
            if (mCurrentDreamToken == token) {
                stopDreamLocked(immediate);
            }
        }
    }

    private void testDreamInternal(ComponentName dream, int userId) {
        synchronized (mLock) {
            startDreamLocked(dream, true /*isTest*/, false /*canDoze*/, userId);
        }
    }

    private void startDreamInternal(boolean doze) {
        final int userId = ActivityManager.getCurrentUser();
        final ComponentName dream = chooseDreamForUser(doze, userId);
        if (dream != null) {
            synchronized (mLock) {
                startDreamLocked(dream, false /*isTest*/, doze, userId);
            }
        }
    }

    private void stopDreamInternal(boolean immediate) {
        synchronized (mLock) {
            stopDreamLocked(immediate);
        }
    }

    private void startDozingInternal(IBinder token, int screenState,
            int screenBrightness) {
        if (DEBUG) {
            Slog.d(TAG, "Dream requested to start dozing: " + token
                    + ", screenState=" + screenState
                    + ", screenBrightness=" + screenBrightness);
        }

        synchronized (mLock) {
            if (mCurrentDreamToken == token && mCurrentDreamCanDoze) {
                mCurrentDreamDozeScreenState = screenState;
                mCurrentDreamDozeScreenBrightness = screenBrightness;
                mPowerManagerInternal.setDozeOverrideFromDreamManager(
                        screenState, screenBrightness);
                if (!mCurrentDreamIsDozing) {
                    mCurrentDreamIsDozing = true;
                    mDozeWakeLock.acquire();
                }
            }
        }
    }

    private void stopDozingInternal(IBinder token) {
        if (DEBUG) {
            Slog.d(TAG, "Dream requested to stop dozing: " + token);
        }

        synchronized (mLock) {
            if (mCurrentDreamToken == token && mCurrentDreamIsDozing) {
                mCurrentDreamIsDozing = false;
                mDozeWakeLock.release();
                mPowerManagerInternal.setDozeOverrideFromDreamManager(
                        Display.STATE_UNKNOWN, PowerManager.BRIGHTNESS_DEFAULT);
            }
        }
    }

    private ComponentName chooseDreamForUser(boolean doze, int userId) {
        if (doze) {
            ComponentName dozeComponent = getDozeComponent(userId);
            return validateDream(dozeComponent) ? dozeComponent : null;
        }
        ComponentName[] dreams = getDreamComponentsForUser(userId);
        return dreams != null && dreams.length != 0 ? dreams[0] : null;
    }

    private boolean validateDream(ComponentName component) {
        if (component == null) return false;
        final ServiceInfo serviceInfo = getServiceInfo(component);
        if (serviceInfo == null) {
            Slog.w(TAG, "Dream " + component + " does not exist");
            return false;
        } else if (serviceInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP
                && !BIND_DREAM_SERVICE.equals(serviceInfo.permission)) {
            Slog.w(TAG, "Dream " + component
                    + " is not available because its manifest is missing the " + BIND_DREAM_SERVICE
                    + " permission on the dream service declaration.");
            return false;
        }
        return true;
    }

    private ComponentName[] getDreamComponentsForUser(int userId) {
        String names = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                Settings.Secure.SCREENSAVER_COMPONENTS,
                userId);
        ComponentName[] components = componentsFromString(names);

        // first, ensure components point to valid services
        List<ComponentName> validComponents = new ArrayList<ComponentName>();
        if (components != null) {
            for (ComponentName component : components) {
                if (validateDream(component)) {
                    validComponents.add(component);
                }
            }
        }

        // fallback to the default dream component if necessary
        if (validComponents.isEmpty()) {
            ComponentName defaultDream = getDefaultDreamComponentForUser(userId);
            if (defaultDream != null) {
                Slog.w(TAG, "Falling back to default dream " + defaultDream);
                validComponents.add(defaultDream);
            }
        }
        return validComponents.toArray(new ComponentName[validComponents.size()]);
    }

    private void setDreamComponentsForUser(int userId, ComponentName[] componentNames) {
        Settings.Secure.putStringForUser(mContext.getContentResolver(),
                Settings.Secure.SCREENSAVER_COMPONENTS,
                componentsToString(componentNames),
                userId);
    }

    private ComponentName getDefaultDreamComponentForUser(int userId) {
        String name = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
                userId);
        return name == null ? null : ComponentName.unflattenFromString(name);
    }

    private ComponentName getDozeComponent() {
        return getDozeComponent(ActivityManager.getCurrentUser());
    }

    private ComponentName getDozeComponent(int userId) {
        // Read the component from a system property to facilitate debugging.
        // Note that for production devices, the dream should actually be declared in
        // a config.xml resource.
        String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
        if (TextUtils.isEmpty(name)) {
            // Read the component from a config.xml resource.
            // The value should be specified in a resource overlay for the product.
            name = mContext.getResources().getString(
                    com.android.internal.R.string.config_dozeComponent);
        }
        boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.DOZE_ENABLED, 1, userId) != 0;
        return TextUtils.isEmpty(name) || !enabled ? null : ComponentName.unflattenFromString(name);
    }

    private ServiceInfo getServiceInfo(ComponentName name) {
        try {
            return name != null ? mContext.getPackageManager().getServiceInfo(name, 0) : null;
        } catch (NameNotFoundException e) {
            return null;
        }
    }

    private void startDreamLocked(final ComponentName name,
            final boolean isTest, final boolean canDoze, final int userId) {
        if (Objects.equal(mCurrentDreamName, name)
                && mCurrentDreamIsTest == isTest
                && mCurrentDreamCanDoze == canDoze
                && mCurrentDreamUserId == userId) {
            return;
        }

        stopDreamLocked(true /*immediate*/);

        Slog.i(TAG, "Entering dreamland.");

        final Binder newToken = new Binder();
        mCurrentDreamToken = newToken;
        mCurrentDreamName = name;
        mCurrentDreamIsTest = isTest;
        mCurrentDreamCanDoze = canDoze;
        mCurrentDreamUserId = userId;

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mController.startDream(newToken, name, isTest, canDoze, userId);
            }
        });
    }

    private void stopDreamLocked(final boolean immediate) {
        if (mCurrentDreamToken != null) {
            if (immediate) {
                Slog.i(TAG, "Leaving dreamland.");
                cleanupDreamLocked();
            } else if (mCurrentDreamIsWaking) {
                return; // already waking
            } else {
                Slog.i(TAG, "Gently waking up from dream.");
                mCurrentDreamIsWaking = true;
            }

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mController.stopDream(immediate);
                }
            });
        }
    }

    private void cleanupDreamLocked() {
        mCurrentDreamToken = null;
        mCurrentDreamName = null;
        mCurrentDreamIsTest = false;
        mCurrentDreamCanDoze = false;
        mCurrentDreamUserId = 0;
        mCurrentDreamIsWaking = false;
        if (mCurrentDreamIsDozing) {
            mCurrentDreamIsDozing = false;
            mDozeWakeLock.release();
        }
        mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
        mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
    }

    private void checkPermission(String permission) {
        if (mContext.checkCallingOrSelfPermission(permission)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
                    + ", must have permission " + permission);
        }
    }

    private static String componentsToString(ComponentName[] componentNames) {
        StringBuilder names = new StringBuilder();
        if (componentNames != null) {
            for (ComponentName componentName : componentNames) {
                if (names.length() > 0) {
                    names.append(',');
                }
                names.append(componentName.flattenToString());
            }
        }
        return names.toString();
    }

    private static ComponentName[] componentsFromString(String names) {
        if (names == null) {
            return null;
        }
        String[] namesArray = names.split(",");
        ComponentName[] componentNames = new ComponentName[namesArray.length];
        for (int i = 0; i < namesArray.length; i++) {
            componentNames[i] = ComponentName.unflattenFromString(namesArray[i]);
        }
        return componentNames;
    }

    private final DreamController.Listener mControllerListener = new DreamController.Listener() {
        @Override
        public void onDreamStopped(Binder token) {
            synchronized (mLock) {
                if (mCurrentDreamToken == token) {
                    cleanupDreamLocked();
                }
            }
        }
    };

    /**
     * Handler for asynchronous operations performed by the dream manager.
     * Ensures operations to {@link DreamController} are single-threaded.
     */
    private final class DreamHandler extends Handler {
        public DreamHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }
    }

    private final class BinderService extends IDreamManager.Stub {
        @Override // Binder call
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
                    != PackageManager.PERMISSION_GRANTED) {
                pw.println("Permission Denial: can't dump DreamManager from from pid="
                        + Binder.getCallingPid()
                        + ", uid=" + Binder.getCallingUid());
                return;
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                dumpInternal(pw);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public ComponentName[] getDreamComponents() {
            checkPermission(android.Manifest.permission.READ_DREAM_STATE);

            final int userId = UserHandle.getCallingUserId();
            final long ident = Binder.clearCallingIdentity();
            try {
                return getDreamComponentsForUser(userId);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void setDreamComponents(ComponentName[] componentNames) {
            checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);

            final int userId = UserHandle.getCallingUserId();
            final long ident = Binder.clearCallingIdentity();
            try {
                setDreamComponentsForUser(userId, componentNames);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public ComponentName getDefaultDreamComponent() {
            checkPermission(android.Manifest.permission.READ_DREAM_STATE);

            final int userId = UserHandle.getCallingUserId();
            final long ident = Binder.clearCallingIdentity();
            try {
                return getDefaultDreamComponentForUser(userId);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public boolean isDreaming() {
            checkPermission(android.Manifest.permission.READ_DREAM_STATE);

            final long ident = Binder.clearCallingIdentity();
            try {
                return isDreamingInternal();
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void dream() {
            checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);

            final long ident = Binder.clearCallingIdentity();
            try {
                requestDreamInternal();
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void testDream(ComponentName dream) {
            if (dream == null) {
                throw new IllegalArgumentException("dream must not be null");
            }
            checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);

            final int callingUserId = UserHandle.getCallingUserId();
            final int currentUserId = ActivityManager.getCurrentUser();
            if (callingUserId != currentUserId) {
                // This check is inherently prone to races but at least it's something.
                Slog.w(TAG, "Aborted attempt to start a test dream while a different "
                        + " user is active: callingUserId=" + callingUserId
                        + ", currentUserId=" + currentUserId);
                return;
            }
            final long ident = Binder.clearCallingIdentity();
            try {
                testDreamInternal(dream, callingUserId);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void awaken() {
            checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);

            final long ident = Binder.clearCallingIdentity();
            try {
                requestAwakenInternal();
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void finishSelf(IBinder token, boolean immediate) {
            // Requires no permission, called by Dream from an arbitrary process.
            if (token == null) {
                throw new IllegalArgumentException("token must not be null");
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                finishSelfInternal(token, immediate);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void startDozing(IBinder token, int screenState, int screenBrightness) {
            // Requires no permission, called by Dream from an arbitrary process.
            if (token == null) {
                throw new IllegalArgumentException("token must not be null");
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                startDozingInternal(token, screenState, screenBrightness);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void stopDozing(IBinder token) {
            // Requires no permission, called by Dream from an arbitrary process.
            if (token == null) {
                throw new IllegalArgumentException("token must not be null");
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                stopDozingInternal(token);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    private final class LocalService extends DreamManagerInternal {
        @Override
        public void startDream(boolean doze) {
            startDreamInternal(doze);
        }

        @Override
        public void stopDream(boolean immediate) {
            stopDreamInternal(immediate);
        }

        @Override
        public boolean isDreaming() {
            return isDreamingInternal();
        }
    }

    private final Runnable mSystemPropertiesChanged = new Runnable() {
        @Override
        public void run() {
            if (DEBUG) Slog.d(TAG, "System properties changed");
            synchronized (mLock) {
                if (mCurrentDreamName != null && mCurrentDreamCanDoze
                        && !mCurrentDreamName.equals(getDozeComponent())) {
                    // May have updated the doze component, wake up
                    mPowerManager.wakeUp(SystemClock.uptimeMillis(),
                            "android.server.dreams:SYSPROP");
                }
            }
        }
    };
}
