Home | History | Annotate | Download | only in server
      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 
     17 package com.android.server;
     18 
     19 import android.content.Context;
     20 import android.content.pm.PackageManager;
     21 import android.os.Handler;
     22 import android.os.IHardwareService;
     23 import android.os.ServiceManager;
     24 import android.os.Message;
     25 import android.util.Slog;
     26 
     27 import java.io.FileInputStream;
     28 import java.io.FileOutputStream;
     29 
     30 public class LightsService {
     31     private static final String TAG = "LightsService";
     32     private static final boolean DEBUG = false;
     33 
     34     static final int LIGHT_ID_BACKLIGHT = 0;
     35     static final int LIGHT_ID_KEYBOARD = 1;
     36     static final int LIGHT_ID_BUTTONS = 2;
     37     static final int LIGHT_ID_BATTERY = 3;
     38     static final int LIGHT_ID_NOTIFICATIONS = 4;
     39     static final int LIGHT_ID_ATTENTION = 5;
     40     static final int LIGHT_ID_BLUETOOTH = 6;
     41     static final int LIGHT_ID_WIFI = 7;
     42     static final int LIGHT_ID_COUNT = 8;
     43 
     44     static final int LIGHT_FLASH_NONE = 0;
     45     static final int LIGHT_FLASH_TIMED = 1;
     46     static final int LIGHT_FLASH_HARDWARE = 2;
     47 
     48     /**
     49      * Light brightness is managed by a user setting.
     50      */
     51     static final int BRIGHTNESS_MODE_USER = 0;
     52 
     53     /**
     54      * Light brightness is managed by a light sensor.
     55      */
     56     static final int BRIGHTNESS_MODE_SENSOR = 1;
     57 
     58     private final Light mLights[] = new Light[LIGHT_ID_COUNT];
     59 
     60     public final class Light {
     61 
     62         private Light(int id) {
     63             mId = id;
     64         }
     65 
     66         public void setBrightness(int brightness) {
     67             setBrightness(brightness, BRIGHTNESS_MODE_USER);
     68         }
     69 
     70         public void setBrightness(int brightness, int brightnessMode) {
     71             synchronized (this) {
     72                 int color = brightness & 0x000000ff;
     73                 color = 0xff000000 | (color << 16) | (color << 8) | color;
     74                 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
     75             }
     76         }
     77 
     78         public void setColor(int color) {
     79             synchronized (this) {
     80                 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
     81             }
     82         }
     83 
     84         public void setFlashing(int color, int mode, int onMS, int offMS) {
     85             synchronized (this) {
     86                 setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
     87             }
     88         }
     89 
     90 
     91         public void pulse() {
     92             pulse(0x00ffffff, 7);
     93         }
     94 
     95         public void pulse(int color, int onMS) {
     96             synchronized (this) {
     97                 if (mColor == 0 && !mFlashing) {
     98                     setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
     99                     mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
    100                 }
    101             }
    102         }
    103 
    104         public void turnOff() {
    105             synchronized (this) {
    106                 setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
    107             }
    108         }
    109 
    110         private void stopFlashing() {
    111             synchronized (this) {
    112                 setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
    113             }
    114         }
    115 
    116         private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
    117             if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
    118                 if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
    119                         + Integer.toHexString(color));
    120                 mColor = color;
    121                 mMode = mode;
    122                 mOnMS = onMS;
    123                 mOffMS = offMS;
    124                 setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
    125             }
    126         }
    127 
    128         private int mId;
    129         private int mColor;
    130         private int mMode;
    131         private int mOnMS;
    132         private int mOffMS;
    133         private boolean mFlashing;
    134     }
    135 
    136     /* This class implements an obsolete API that was removed after eclair and re-added during the
    137      * final moments of the froyo release to support flashlight apps that had been using the private
    138      * IHardwareService API. This is expected to go away in the next release.
    139      */
    140     private final IHardwareService.Stub mLegacyFlashlightHack = new IHardwareService.Stub() {
    141 
    142         private static final String FLASHLIGHT_FILE = "/sys/class/leds/spotlight/brightness";
    143 
    144         public boolean getFlashlightEnabled() {
    145             try {
    146                 FileInputStream fis = new FileInputStream(FLASHLIGHT_FILE);
    147                 int result = fis.read();
    148                 fis.close();
    149                 return (result != '0');
    150             } catch (Exception e) {
    151                 return false;
    152             }
    153         }
    154 
    155         public void setFlashlightEnabled(boolean on) {
    156             if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
    157                     != PackageManager.PERMISSION_GRANTED &&
    158                     mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
    159                     != PackageManager.PERMISSION_GRANTED) {
    160                 throw new SecurityException("Requires FLASHLIGHT or HARDWARE_TEST permission");
    161             }
    162             try {
    163                 FileOutputStream fos = new FileOutputStream(FLASHLIGHT_FILE);
    164                 byte[] bytes = new byte[2];
    165                 bytes[0] = (byte)(on ? '1' : '0');
    166                 bytes[1] = '\n';
    167                 fos.write(bytes);
    168                 fos.close();
    169             } catch (Exception e) {
    170                 // fail silently
    171             }
    172         }
    173     };
    174 
    175     LightsService(Context context) {
    176 
    177         mNativePointer = init_native();
    178         mContext = context;
    179 
    180         ServiceManager.addService("hardware", mLegacyFlashlightHack);
    181 
    182         for (int i = 0; i < LIGHT_ID_COUNT; i++) {
    183             mLights[i] = new Light(i);
    184         }
    185     }
    186 
    187     protected void finalize() throws Throwable {
    188         finalize_native(mNativePointer);
    189         super.finalize();
    190     }
    191 
    192     public Light getLight(int id) {
    193         return mLights[id];
    194     }
    195 
    196     private Handler mH = new Handler() {
    197         @Override
    198         public void handleMessage(Message msg) {
    199             Light light = (Light)msg.obj;
    200             light.stopFlashing();
    201         }
    202     };
    203 
    204     private static native int init_native();
    205     private static native void finalize_native(int ptr);
    206 
    207     private static native void setLight_native(int ptr, int light, int color, int mode,
    208             int onMS, int offMS, int brightnessMode);
    209 
    210     private final Context mContext;
    211 
    212     private int mNativePointer;
    213 }
    214