Home | History | Annotate | Download | only in lights
      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 
     36         private LightImpl(int id) {
     37             mId = id;
     38         }
     39 
     40         @Override
     41         public void setBrightness(int brightness) {
     42             setBrightness(brightness, BRIGHTNESS_MODE_USER);
     43         }
     44 
     45         @Override
     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
     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 (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
     93         public void turnOff() {
     94             synchronized (this) {
     95                 setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
     96             }
     97         }
     98 
     99         @Override
    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 
    119         private void stopFlashing() {
    120             synchronized (this) {
    121                 setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
    122             }
    123         }
    124 
    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 
    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 
    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
    180     public void onStart() {
    181         publishLocalService(LightsManager.class, mService);
    182     }
    183 
    184     @Override
    185     public void onBootPhase(int phase) {
    186     }
    187 
    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 
    215     static native void setLight_native(int light, int color, int mode,
    216             int onMS, int offMS, int brightnessMode);
    217 }
    218