13a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood/*
23a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * Copyright (C) 2008 The Android Open Source Project
33a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood *
43a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
53a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * you may not use this file except in compliance with the License.
63a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * You may obtain a copy of the License at
73a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood *
83a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
93a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood *
103a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * Unless required by applicable law or agreed to in writing, software
113a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
123a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * See the License for the specific language governing permissions and
143a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood * limitations under the License.
153a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood */
163a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
173a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodpackage com.android.server;
183a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
193a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.content.Context;
20eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport android.content.pm.PackageManager;
213a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.Handler;
22eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport android.os.IHardwareService;
23eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport android.os.ServiceManager;
243a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.Message;
258a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
263a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
27eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport java.io.File;
28eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport java.io.FileInputStream;
29eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwoodimport java.io.FileOutputStream;
30eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
313a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodpublic class LightsService {
323a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static final String TAG = "LightsService";
333a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
343a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_BACKLIGHT = 0;
353a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_KEYBOARD = 1;
363a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_BUTTONS = 2;
373a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_BATTERY = 3;
383a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_NOTIFICATIONS = 4;
393a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_ID_ATTENTION = 5;
403cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    static final int LIGHT_ID_BLUETOOTH = 6;
413cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    static final int LIGHT_ID_WIFI = 7;
423cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    static final int LIGHT_ID_COUNT = 8;
433a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
443a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_FLASH_NONE = 0;
453a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_FLASH_TIMED = 1;
463a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int LIGHT_FLASH_HARDWARE = 2;
473a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
483a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    /**
493a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood     * Light brightness is managed by a user setting.
503a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood     */
513a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int BRIGHTNESS_MODE_USER = 0;
523a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
533a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    /**
543a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood     * Light brightness is managed by a light sensor.
553a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood     */
563a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    static final int BRIGHTNESS_MODE_SENSOR = 1;
573a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
583cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    private final Light mLights[] = new Light[LIGHT_ID_COUNT];
593a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
603cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    public final class Light {
613a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
623cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private Light(int id) {
633cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            mId = id;
643cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
653a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
663cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void setBrightness(int brightness) {
673cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            setBrightness(brightness, BRIGHTNESS_MODE_USER);
683cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
693a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
703cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void setBrightness(int brightness, int brightnessMode) {
713cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
723cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                int color = brightness & 0x000000ff;
733cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                color = 0xff000000 | (color << 16) | (color << 8) | color;
743cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
753cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            }
763cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
773a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
783cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void setColor(int color) {
793cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
803cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, 0);
813cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            }
823cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
833a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
843cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void setFlashing(int color, int mode, int onMS, int offMS) {
853cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
863cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLightLocked(color, mode, onMS, offMS, BRIGHTNESS_MODE_USER);
873cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            }
883cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
893a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
90670f93283b5e2445c58998153de9c476acddc37bMike Lockwood
913cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void pulse() {
92670f93283b5e2445c58998153de9c476acddc37bMike Lockwood            pulse(0x00ffffff, 7);
93670f93283b5e2445c58998153de9c476acddc37bMike Lockwood        }
94670f93283b5e2445c58998153de9c476acddc37bMike Lockwood
95670f93283b5e2445c58998153de9c476acddc37bMike Lockwood        public void pulse(int color, int onMS) {
963cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
973cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                if (mColor == 0 && !mFlashing) {
98670f93283b5e2445c58998153de9c476acddc37bMike Lockwood                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
99670f93283b5e2445c58998153de9c476acddc37bMike Lockwood                    mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
1003cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                }
1013cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            }
1023cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
1033a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
1043cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        public void turnOff() {
1053cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
1063cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, 0);
1073cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            }
1083a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood        }
1093a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
1103cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private void stopFlashing() {
1113cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            synchronized (this) {
1123cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLightLocked(mColor, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_USER);
1133a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood            }
1143cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
1153cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
1163cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
1173cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
1183cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                mColor = color;
1193cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                mMode = mode;
1203cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                mOnMS = onMS;
1213cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                mOffMS = offMS;
1223cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood                setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
1233a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood            }
1243a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood        }
1253cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
1263cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private int mId;
1273cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private int mColor;
1283cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private int mMode;
1293cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private int mOnMS;
1303cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private int mOffMS;
1313cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        private boolean mFlashing;
1323cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    }
1333cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
134eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood    /* This class implements an obsolete API that was removed after eclair and re-added during the
135eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood     * final moments of the froyo release to support flashlight apps that had been using the private
136eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood     * IHardwareService API. This is expected to go away in the next release.
137eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood     */
138eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood    private final IHardwareService.Stub mLegacyFlashlightHack = new IHardwareService.Stub() {
139eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
140eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        private static final String FLASHLIGHT_FILE = "/sys/class/leds/spotlight/brightness";
141eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
142eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        public boolean getFlashlightEnabled() {
143eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            try {
144eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                FileInputStream fis = new FileInputStream(FLASHLIGHT_FILE);
145eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                int result = fis.read();
146eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                fis.close();
147eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                return (result != '0');
148eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            } catch (Exception e) {
149eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                Slog.e(TAG, "getFlashlightEnabled failed", e);
150eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                return false;
151eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            }
152eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        }
153eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
154eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        public void setFlashlightEnabled(boolean on) {
155eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.FLASHLIGHT)
156eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                    != PackageManager.PERMISSION_GRANTED &&
157eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                    mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST)
158eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                    != PackageManager.PERMISSION_GRANTED) {
159eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                throw new SecurityException("Requires FLASHLIGHT or HARDWARE_TEST permission");
160eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            }
161eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            try {
162eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                FileOutputStream fos = new FileOutputStream(FLASHLIGHT_FILE);
163eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                byte[] bytes = new byte[2];
164eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                bytes[0] = (byte)(on ? '1' : '0');
165eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                bytes[1] = '\n';
166eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                fos.write(bytes);
167eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                fos.close();
168eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            } catch (Exception e) {
169eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood                Slog.e(TAG, "setFlashlightEnabled failed", e);
170eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood            }
171eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        }
172eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood    };
173eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
1743cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    LightsService(Context context) {
1753cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
1763cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        mNativePointer = init_native();
1773cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        mContext = context;
1783cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
179eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood        ServiceManager.addService("hardware", mLegacyFlashlightHack);
180eb9cbb8fdddf4c887004b20b504083035d57a15fMike Lockwood
1813cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        for (int i = 0; i < LIGHT_ID_COUNT; i++) {
1823cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            mLights[i] = new Light(i);
1833cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        }
1843cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    }
1853cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
1863cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    protected void finalize() throws Throwable {
1873cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        finalize_native(mNativePointer);
1883cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        super.finalize();
1893cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    }
1903cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood
1913cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood    public Light getLight(int id) {
1923cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood        return mLights[id];
1933a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    }
1943a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
1953a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private Handler mH = new Handler() {
1963a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood        @Override
1973a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood        public void handleMessage(Message msg) {
1983cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            Light light = (Light)msg.obj;
1993cb67a37f185a7a5b12712907630acb68e0ac402Mike Lockwood            light.stopFlashing();
2003a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood        }
2013a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    };
2023a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
2033a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static native int init_native();
2043a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static native void finalize_native(int ptr);
2053a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
2063a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static native void setLight_native(int ptr, int light, int color, int mode,
2073a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood            int onMS, int offMS, int brightnessMode);
2083a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
2093a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private final Context mContext;
2103a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood
2113a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private int mNativePointer;
2123a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood}
213