LightsService.java revision 49506e089103e8fe38d10e0589688e51cceacaf2
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.lights;
18
19import com.android.server.SystemService;
20import com.android.server.vr.VrManagerService;
21
22import android.app.ActivityManager;
23import android.content.Context;
24import android.os.Handler;
25import android.os.Message;
26import android.os.RemoteException;
27import android.os.Trace;
28import android.os.UserHandle;
29import android.provider.Settings;
30import android.service.vr.IVrManager;
31import android.service.vr.IVrStateCallbacks;
32import android.util.Slog;
33
34public class LightsService extends SystemService {
35    static final String TAG = "LightsService";
36    static final boolean DEBUG = false;
37
38    final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
39    private boolean mVrModeEnabled;
40
41    private final class LightImpl extends Light {
42
43        private LightImpl(int id) {
44            mId = id;
45        }
46
47        @Override
48        public void setBrightness(int brightness) {
49            setBrightness(brightness, BRIGHTNESS_MODE_USER);
50        }
51
52        @Override
53        public void setBrightness(int brightness, int brightnessMode) {
54            synchronized (this) {
55                int color = brightness & 0x000000ff;
56                color = 0xff000000 | (color << 16) | (color << 8) | color;
57                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
58            }
59        }
60
61        @Override
62        public void setColor(int color) {
63            synchronized (this) {
64                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
65            }
66        }
67
68        @Override
69        public void setFlashing(int color, int mode, int onMS, int offMS) {
70            synchronized (this) {
71                setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
72            }
73        }
74
75        @Override
76        public void pulse() {
77            pulse(0x00ffffff, 7);
78        }
79
80        @Override
81        public void pulse(int color, int onMS) {
82            synchronized (this) {
83                if (mBrightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
84                    return;
85                }
86                if (mColor == 0 && !mFlashing) {
87                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
88                    mColor = 0;
89                    mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
90                }
91            }
92        }
93
94        @Override
95        public void turnOff() {
96            synchronized (this) {
97                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
98            }
99        }
100
101        void enableLowPersistence() {
102            synchronized(this) {
103                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_LOW_PERSISTENCE);
104                mLocked = true;
105            }
106        }
107
108        void disableLowPersistence() {
109            synchronized(this) {
110                mLocked = false;
111                setLightLocked(mLastColor, LIGHT_FLASH_NONE, 0, 0, mLastBrightnessMode);
112            }
113        }
114
115        private void stopFlashing() {
116            synchronized (this) {
117                setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
118            }
119        }
120
121        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
122            if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
123                    mBrightnessMode != brightnessMode)) {
124                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
125                        + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
126                mLastColor = mColor;
127                mColor = color;
128                mMode = mode;
129                mOnMS = onMS;
130                mOffMS = offMS;
131                mLastBrightnessMode = mBrightnessMode;
132                mBrightnessMode = brightnessMode;
133                Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
134                        + Integer.toHexString(color) + ")");
135                try {
136                    setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
137                } finally {
138                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
139                }
140            }
141        }
142
143        private int mId;
144        private int mColor;
145        private int mMode;
146        private int mOnMS;
147        private int mOffMS;
148        private boolean mFlashing;
149        private int mBrightnessMode;
150        private int mLastBrightnessMode;
151        private int mLastColor;
152        private boolean mLocked;
153    }
154
155    public LightsService(Context context) {
156        super(context);
157
158        mNativePointer = init_native();
159
160        for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
161            mLights[i] = new LightImpl(i);
162        }
163    }
164
165    @Override
166    public void onStart() {
167        publishLocalService(LightsManager.class, mService);
168    }
169
170    @Override
171    public void onBootPhase(int phase) {
172        if (phase == PHASE_SYSTEM_SERVICES_READY) {
173            IVrManager vrManager =
174                    (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
175            try {
176                vrManager.registerListener(mVrStateCallbacks);
177            } catch (RemoteException e) {
178                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
179            }
180        }
181    }
182
183    private int getVrDisplayMode() {
184        int currentUser = ActivityManager.getCurrentUser();
185        return Settings.Secure.getIntForUser(getContext().getContentResolver(),
186                Settings.Secure.VR_DISPLAY_MODE,
187                /*default*/Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE,
188                currentUser);
189    }
190
191    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
192        @Override
193        public void onVrStateChanged(boolean enabled) throws RemoteException {
194            LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT];
195            int vrDisplayMode = getVrDisplayMode();
196
197            // User leaves VR mode before altering display settings.
198            if (enabled && vrDisplayMode == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE) {
199                if (!mVrModeEnabled) {
200                    if (DEBUG)
201                        Slog.v(TAG, "VR mode enabled, setting brightness to low persistence");
202                    l.enableLowPersistence();
203                    mVrModeEnabled = true;
204                }
205            } else {
206                if (mVrModeEnabled) {
207                    if (DEBUG) Slog.v(TAG, "VR mode disabled, resetting brightnes");
208                    l.disableLowPersistence();
209                    mVrModeEnabled = false;
210                }
211            }
212        }
213    };
214
215    private final LightsManager mService = new LightsManager() {
216        @Override
217        public Light getLight(int id) {
218            if (id < LIGHT_ID_COUNT) {
219                return mLights[id];
220            } else {
221                return null;
222            }
223        }
224    };
225
226    @Override
227    protected void finalize() throws Throwable {
228        finalize_native(mNativePointer);
229        super.finalize();
230    }
231
232    private Handler mH = new Handler() {
233        @Override
234        public void handleMessage(Message msg) {
235            LightImpl light = (LightImpl)msg.obj;
236            light.stopFlashing();
237        }
238    };
239
240    private static native long init_native();
241    private static native void finalize_native(long ptr);
242
243    static native void setLight_native(long ptr, int light, int color, int mode,
244            int onMS, int offMS, int brightnessMode);
245
246    private long mNativePointer;
247}
248