111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown/*
211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * Copyright (C) 2012 The Android Open Source Project
311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown *
411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * you may not use this file except in compliance with the License.
611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * You may obtain a copy of the License at
711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown *
811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown *
1011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * Unless required by applicable law or agreed to in writing, software
1111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * See the License for the specific language governing permissions and
1411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * limitations under the License.
1511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown */
1611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
1711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownpackage android.service.dreams;
1811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
1911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.content.ComponentName;
2011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.content.Context;
2111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.content.Intent;
2211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.os.PowerManager;
2311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.os.RemoteException;
2411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.os.ServiceManager;
2511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.os.SystemClock;
2611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.os.UserHandle;
2711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.provider.Settings;
2811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownimport android.util.Slog;
2911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
3011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown/**
3111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * Internal helper for launching dreams to ensure consistency between the
3211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
3311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown *
3411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown * @hide
3511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown */
3611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brownpublic final class Sandman {
3711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private static final String TAG = "Sandman";
3811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
3911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    // The component name of a special dock app that merely launches a dream.
4011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    // We don't want to launch this app when docked because it causes an unnecessary
4111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    // activity transition.  We just want to start the dream.
4211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private static final ComponentName SOMNAMBULATOR_COMPONENT =
4311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator");
4411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
4511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
4611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    // The sandman is eternal.  No one instantiates him.
4711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private Sandman() {
4811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
4911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
5011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    /**
5111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     * Returns true if the specified dock app intent should be started.
5211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     * False if we should dream instead, if appropriate.
5311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     */
5411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    public static boolean shouldStartDockApp(Context context, Intent intent) {
5511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        ComponentName name = intent.resolveActivity(context.getPackageManager());
5611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        return name != null && !name.equals(SOMNAMBULATOR_COMPONENT);
5711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
5811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
5911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    /**
6011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     * Starts a dream manually.
6111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     */
6211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    public static void startDreamByUserRequest(Context context) {
6311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        startDream(context, false);
6411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
6511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
6611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    /**
6711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     * Starts a dream when docked if the system has been configured to do so,
6811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     * otherwise does nothing.
6911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown     */
7011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    public static void startDreamWhenDockedIfAppropriate(Context context) {
7111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        if (!isScreenSaverEnabled(context)
7211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                || !isScreenSaverActivatedOnDock(context)) {
7311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            Slog.i(TAG, "Dreams currently disabled for docks.");
7411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            return;
7511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        }
7611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
7711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        startDream(context, true);
7811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
7911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
8011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private static void startDream(Context context, boolean docked) {
8111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        try {
8211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
8311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    ServiceManager.getService(DreamService.DREAM_SERVICE));
8411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
8511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                if (docked) {
8611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    Slog.i(TAG, "Activating dream while docked.");
8711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
8811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    // Wake up.
8911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    // The power manager will wake up the system automatically when it starts
9011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    // receiving power from a dock but there is a race between that happening
9111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    // and the UI mode manager starting a dream.  We want the system to already
9211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    // be awake by the time this happens.  Otherwise the dream may not start.
9311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    PowerManager powerManager =
9411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                            (PowerManager)context.getSystemService(Context.POWER_SERVICE);
9511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    powerManager.wakeUp(SystemClock.uptimeMillis());
9611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                } else {
9711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                    Slog.i(TAG, "Activating dream by user request.");
9811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                }
9911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
10011159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                // Dream.
10111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                dreamManagerService.dream();
10211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            }
10311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        } catch (RemoteException ex) {
10411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown            Slog.e(TAG, "Could not start dream when docked.", ex);
10511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        }
10611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
10711159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
10811159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private static boolean isScreenSaverEnabled(Context context) {
109ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock        int def = context.getResources().getBoolean(
110ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock                com.android.internal.R.bool.config_dreamsEnabledByDefault) ? 1 : 0;
11111159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        return Settings.Secure.getIntForUser(context.getContentResolver(),
112ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock                Settings.Secure.SCREENSAVER_ENABLED, def,
11311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown                UserHandle.USER_CURRENT) != 0;
11411159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
11511159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown
11611159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    private static boolean isScreenSaverActivatedOnDock(Context context) {
117ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock        int def = context.getResources().getBoolean(
118ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault) ? 1 : 0;
11911159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown        return Settings.Secure.getIntForUser(context.getContentResolver(),
120ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock                Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, def,
121ed108f3d125b0a4cc465057e3514caf781cdea19John Spurlock                UserHandle.USER_CURRENT) != 0;
12211159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown    }
12311159e9a785a143c9f3765bdf5a5ccfd77842d7aJeff Brown}
124