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