1 /* * Copyright (C) 2008 The Android Open Source Project 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package com.android.server.lights; 17 18 import com.android.server.SystemService; 19 20 import android.app.ActivityManager; 21 import android.content.Context; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.os.Trace; 25 import android.provider.Settings; 26 import android.util.Slog; 27 28 public class LightsService extends SystemService { 29 static final String TAG = "LightsService"; 30 static final boolean DEBUG = false; 31 32 final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT]; 33 34 private final class LightImpl extends Light { 35 LightImpl(int id)36 private LightImpl(int id) { 37 mId = id; 38 } 39 40 @Override setBrightness(int brightness)41 public void setBrightness(int brightness) { 42 setBrightness(brightness, BRIGHTNESS_MODE_USER); 43 } 44 45 @Override setBrightness(int brightness, int brightnessMode)46 public void setBrightness(int brightness, int brightnessMode) { 47 synchronized (this) { 48 // LOW_PERSISTENCE cannot be manually set 49 if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) { 50 Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId + 51 ": brightness=0x" + Integer.toHexString(brightness)); 52 return; 53 } 54 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 setColor(int color)62 public void setColor(int color) { 63 synchronized (this) { 64 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0); 65 } 66 } 67 68 @Override setFlashing(int color, int mode, int onMS, int offMS)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 pulse()76 public void pulse() { 77 pulse(0x00ffffff, 7); 78 } 79 80 @Override pulse(int color, int onMS)81 public void pulse(int color, int onMS) { 82 synchronized (this) { 83 if (mColor == 0 && !mFlashing) { 84 setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, 85 BRIGHTNESS_MODE_USER); 86 mColor = 0; 87 mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS); 88 } 89 } 90 } 91 92 @Override turnOff()93 public void turnOff() { 94 synchronized (this) { 95 setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0); 96 } 97 } 98 99 @Override setVrMode(boolean enabled)100 public void setVrMode(boolean enabled) { 101 synchronized (this) { 102 if (mVrModeEnabled != enabled) { 103 mVrModeEnabled = enabled; 104 105 mUseLowPersistenceForVR = 106 (getVrDisplayMode() == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE); 107 if (shouldBeInLowPersistenceMode()) { 108 mLastBrightnessMode = mBrightnessMode; 109 } 110 111 // NOTE: We do not trigger a call to setLightLocked here. We do not know the 112 // current brightness or other values when leaving VR so we avoid any incorrect 113 // jumps. The code that calls this method will immediately issue a brightness 114 // update which is when the change will occur. 115 } 116 } 117 } 118 stopFlashing()119 private void stopFlashing() { 120 synchronized (this) { 121 setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER); 122 } 123 } 124 setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode)125 private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) { 126 if (shouldBeInLowPersistenceMode()) { 127 brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE; 128 } else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) { 129 brightnessMode = mLastBrightnessMode; 130 } 131 132 if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS || 133 offMS != mOffMS || mBrightnessMode != brightnessMode) { 134 if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" 135 + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode); 136 mInitialized = true; 137 mLastColor = mColor; 138 mColor = color; 139 mMode = mode; 140 mOnMS = onMS; 141 mOffMS = offMS; 142 mBrightnessMode = brightnessMode; 143 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x" 144 + Integer.toHexString(color) + ")"); 145 try { 146 setLight_native(mId, color, mode, onMS, offMS, brightnessMode); 147 } finally { 148 Trace.traceEnd(Trace.TRACE_TAG_POWER); 149 } 150 } 151 } 152 shouldBeInLowPersistenceMode()153 private boolean shouldBeInLowPersistenceMode() { 154 return mVrModeEnabled && mUseLowPersistenceForVR; 155 } 156 157 private int mId; 158 private int mColor; 159 private int mMode; 160 private int mOnMS; 161 private int mOffMS; 162 private boolean mFlashing; 163 private int mBrightnessMode; 164 private int mLastBrightnessMode; 165 private int mLastColor; 166 private boolean mVrModeEnabled; 167 private boolean mUseLowPersistenceForVR; 168 private boolean mInitialized; 169 } 170 LightsService(Context context)171 public LightsService(Context context) { 172 super(context); 173 174 for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) { 175 mLights[i] = new LightImpl(i); 176 } 177 } 178 179 @Override onStart()180 public void onStart() { 181 publishLocalService(LightsManager.class, mService); 182 } 183 184 @Override onBootPhase(int phase)185 public void onBootPhase(int phase) { 186 } 187 getVrDisplayMode()188 private int getVrDisplayMode() { 189 int currentUser = ActivityManager.getCurrentUser(); 190 return Settings.Secure.getIntForUser(getContext().getContentResolver(), 191 Settings.Secure.VR_DISPLAY_MODE, 192 /*default*/Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE, 193 currentUser); 194 } 195 196 private final LightsManager mService = new LightsManager() { 197 @Override 198 public Light getLight(int id) { 199 if (0 <= id && id < LIGHT_ID_COUNT) { 200 return mLights[id]; 201 } else { 202 return null; 203 } 204 } 205 }; 206 207 private Handler mH = new Handler() { 208 @Override 209 public void handleMessage(Message msg) { 210 LightImpl light = (LightImpl)msg.obj; 211 light.stopFlashing(); 212 } 213 }; 214 setLight_native(int light, int color, int mode, int onMS, int offMS, int brightnessMode)215 static native void setLight_native(int light, int color, int mode, 216 int onMS, int offMS, int brightnessMode); 217 } 218