通知灯

通知灯的使用请:

private void RedFlashLight()
{
NotificationManager nm = ( NotificationManager ) getSystemService( NOTIFICATION_SERVICE );
Notification notif = new Notification();
notif.ledARGB = 0xFFff0000;
notif.flags = Notification.FLAG_SHOW_LIGHTS;
notif.ledOnMS = 100; 
notif.ledOffMS = 100; 
nm.notify(LED_NOTIFICATION_ID, notif);
}





 Android中有各种灯,背光灯,按键灯,指示灯,等等;前几天修改了这部分代码,整理下思路,其实都不难;

       首先,来说说指示灯(提示灯),即未接电话,未接短信的时候,会闪灯,这个其实就是NotificationManager这个类中的notify()方法来处理的;流程简单来过一下:


       Step 1:从应用层发送的notify(),到framework层被NotificationManager.Java这个类接受了,来看看这个notify()这个方法:

[java]  view plain  copy
 
  1. public void notify(int id, Notification notification)  
  2.     {  
  3.         notify(null, id, notification);  
  4.     }  

[java]  view plain  copy
 
  1. public void notify(String tag, int id, Notification notification)  
  2.    {  
  3.        int[] idOut = new int[1];  
  4.        INotificationManager service = getService();  
  5.        String pkg = mContext.getPackageName();  
  6.        if (notification.sound != null) {  
  7.            notification.sound = notification.sound.getCanonicalUri();  
  8.        }  
  9.        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");  
  10.        try {  
  11.            service.enqueueNotificationWithTag(pkg, tag, id, notification, idOut,  
  12.                    UserHandle.myUserId());  
  13.            if (id != idOut[0]) {  
  14.                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);  
  15.            }  
  16.        } catch (RemoteException e) {  
  17.        }  
  18.    }  
重点关注这个enqueueNotificationWithTag()这个方法,这个方法首先会取是否传递过来了声音的Uri,如果传递了,就保存下来,给等会播放用;


     Step 2:enqueueNotificationWithTag()这个方法调用到了NotificationManagerService.java这个类中去了,来看看这个方法:

[java]  view plain  copy
 
  1. public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,  
  2.             int[] idOut, int userId)  
  3.     {  
  4.         enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),  
  5.                 tag, id, notification, idOut, userId);  
  6.     }  

[java]  view plain  copy
 
  1. // Not exposed via Binder; for system use only (otherwise malicious apps could spoof the  
  2.     // uid/pid of another application)  
  3.     public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,  
  4.             String tag, int id, Notification notification, int[] idOut, int userId)  
  5.     {  
  6.         if (DBG) {  
  7.             Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification + ", notification.ledARGB : "+ notification.ledARGB);  
  8.         }  
  9.         checkCallerIsSystemOrSameApp(pkg);  
  10.         final boolean isSystemNotification = ("android".equals(pkg));  
  11.   
  12.         userId = ActivityManager.handleIncomingUser(callingPid,  
  13.                 callingUid, userId, truefalse"enqueueNotification", pkg);  
  14.         UserHandle user = new UserHandle(userId);  
  15.   
  16.         // Limit the number of notifications that any given package except the android  
  17.         // package can enqueue.  Prevents DOS attacks and deals with leaks.  
  18.         if (!isSystemNotification) {  
  19.             synchronized (mNotificationList) {  
  20.                 int count = 0;  
  21.                 int eldestIdx = 0;  
  22.                 long eldestTime = 0;  
  23.                 final int N = mNotificationList.size();  
  24.                 for (int i=0; i<N; i++) {  
  25.                     NotificationRecord r = mNotificationList.get(i);  
  26.                     if (r.pkg.equals(pkg) && r.userId == userId) {  
  27.                         if (count == 0) {  
  28.                             eldestTime = r.notification.when;  
  29.                             eldestIdx = i;  
  30.                         }  
  31.                         else {  
  32.                             if (r.notification.when < eldestTime) {  
  33.                                 eldestTime = r.notification.when;  
  34.                                 eldestIdx = i;  
  35.                             }  
  36.                         }  
  37.                         count++;  
  38.                         if (count >= MAX_PACKAGE_NOTIFICATIONS) {  
  39.                             Slog.e(TAG, "Package has already posted " + count  
  40.                                     + " notifications.  Not showing more.  package=" + pkg);  
  41.                             //return;  
  42.                             // [ALPS00447419] SystemUI OOM: remove eldest entry  
  43.                             r = mNotificationList.get(eldestIdx);  
  44.                             mNotificationList.remove(eldestIdx);  
  45.                             cancelNotificationLocked(r, true);  
  46.                             break;  
  47.                         }  
  48.                     }  
  49.                 }  
  50.             }  
  51.         }  
  52.   
  53.         // This conditional is a dirty hack to limit the logging done on  
  54.         //     behalf of the download manager without affecting other apps.  
  55.         if (!pkg.equals("com.android.providers.downloads")  
  56.                 || Log.isLoggable("DownloadManager", Log.VERBOSE)) {  
  57.             EventLog.writeEvent(EventLogTags.NOTIFICATION_ENQUEUE, pkg, id, tag, userId,  
  58.                     notification.toString());  
  59.         }  
  60.   
  61.         if (pkg == null || notification == null) {  
  62.             throw new IllegalArgumentException("null not allowed: pkg=" + pkg  
  63.                     + " id=" + id + " notification=" + notification);  
  64.         }  
  65.         if (notification.icon != 0) {  
  66.             if (notification.contentView == null) {  
  67.                 throw new IllegalArgumentException("contentView required: pkg=" + pkg  
  68.                         + " id=" + id + " notification=" + notification);  
  69.             }  
  70.         }  
  71.   
  72.         // === Scoring ===  
  73.   
  74.         // 0. Sanitize inputs  
  75.         notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX);  
  76.         // Migrate notification flags to scores  
  77.         if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) {  
  78.             if (notification.priority < Notification.PRIORITY_MAX) notification.priority = Notification.PRIORITY_MAX;  
  79.         } else if (SCORE_ONGOING_HIGHER && 0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {  
  80.             if (notification.priority < Notification.PRIORITY_HIGH) notification.priority = Notification.PRIORITY_HIGH;  
  81.         }  
  82.   
  83.         // 1. initial score: buckets of 10, around the app   
  84.         int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER; //[-20..20]  
  85.   
  86.         // 2. Consult external heuristics (TBD)  
  87.   
  88.         // 3. Apply local rules  
  89.   
  90.         // blocked apps  
  91.         if (ENABLE_BLOCKED_NOTIFICATIONS && !isSystemNotification && !areNotificationsEnabledForPackageInt(pkg)) {  
  92.             score = JUNK_SCORE;  
  93.             Slog.e(TAG, "Suppressing notification from package " + pkg + " by user request.");  
  94.         }  
  95.   
  96.         if (DBG) {  
  97.             Slog.v(TAG, "Assigned score=" + score + " to " + notification);  
  98.         }  
  99.   
  100.         if (score < SCORE_DISPLAY_THRESHOLD) {  
  101.             // Notification will be blocked because the score is too low.  
  102.             return;  
  103.         }  
  104.   
  105.         // Should this notification make noise, vibe, or use the LED?  
  106.         final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD);  
  107.   
  108.         synchronized (mNotificationList) {  
  109.             NotificationRecord r = new NotificationRecord(pkg, tag, id,   
  110.                     callingUid, callingPid, userId,  
  111.                     score,  
  112.                     notification);  
  113.             NotificationRecord old = null;  
  114.   
  115.             int index = indexOfNotificationLocked(pkg, tag, id, userId);  
  116.             if (index < 0) {  
  117.                 mNotificationList.add(r);  
  118.             } else {  
  119.                 old = mNotificationList.remove(index);  
  120.                 mNotificationList.add(index, r);  
  121.                 // Make sure we don't lose the foreground service state.  
  122.                 if (old != null) {  
  123.                     notification.flags |=  
  124.                         old.notification.flags&Notification.FLAG_FOREGROUND_SERVICE;  
  125.                 }  
  126.             }  
  127.   
  128.             // Ensure if this is a foreground service that the proper additional  
  129.             // flags are set.  
  130.             if ((notification.flags&Notification.FLAG_FOREGROUND_SERVICE) != 0) {  
  131.                 notification.flags |= Notification.FLAG_ONGOING_EVENT  
  132.                         | Notification.FLAG_NO_CLEAR;  
  133.             }  
  134.   
  135.             final int currentUser;  
  136.             final long token = Binder.clearCallingIdentity();  
  137.             try {  
  138.                 currentUser = ActivityManager.getCurrentUser();  
  139.             } finally {  
  140.                 Binder.restoreCallingIdentity(token);  
  141.             }  
  142.   
  143.             if (notification.icon != 0) {  
  144.                 final StatusBarNotification n = new StatusBarNotification(  
  145.                         pkg, id, tag, r.uid, r.initialPid, score, notification, user);  
  146.                 if (old != null && old.statusBarKey != null) {  
  147.                     r.statusBarKey = old.statusBarKey;  
  148.                     long identity = Binder.clearCallingIdentity();  
  149.                     try {  
  150.                         mStatusBar.updateNotification(r.statusBarKey, n);  
  151.                     }  
  152.                     finally {  
  153.                         Binder.restoreCallingIdentity(identity);  
  154.                     }  
  155.                 } else {  
  156.                     long identity = Binder.clearCallingIdentity();  
  157.                     try {  
  158.                         r.statusBarKey = mStatusBar.addNotification(n);  
  159.                         if ((n.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0  
  160.                                 && canInterrupt) {  
  161.                             mAttentionLight.pulse();  
  162.                         }  
  163.                     }  
  164.                     finally {  
  165.                         Binder.restoreCallingIdentity(identity);  
  166.                     }  
  167.                 }  
  168.                 // Send accessibility events only for the current user.  
  169.                 if (currentUser == userId) {  
  170.                     sendAccessibilityEvent(notification, pkg);  
  171.                 }  
  172.             } else {  
  173.                 Slog.e(TAG, "Ignoring notification with icon==0: " + notification);  
  174.                 if (old != null && old.statusBarKey != null) {  
  175.                     long identity = Binder.clearCallingIdentity();  
  176.                     try {  
  177.                         mStatusBar.removeNotification(old.statusBarKey);  
  178.                     }  
  179.                     finally {  
  180.                         Binder.restoreCallingIdentity(identity);  
  181.                     }  
  182.                 }  
  183.             }  
  184.   
  185.             // If we're not supposed to beep, vibrate, etc. then don't.  
  186.             // ensure mms can send notification when a phone is calling  
  187.             if ((((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) || pkg.equals("com.android.mms"))  
  188.                     && (!(old != null  
  189.                         && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))  
  190.                     && (r.userId == UserHandle.USER_ALL ||  
  191.                         (r.userId == userId && r.userId == currentUser))  
  192.                     && canInterrupt  
  193.                     && mSystemReady) {  
  194.                 ///M:   
  195.                 if (DBG) {  
  196.                     Log.d(TAG,"pakage="+pkg+",In NotificationMangerService, this notification soud, leds and vibrate enable");  
  197.                 }  
  198.                 final AudioManager audioManager = (AudioManager) mContext  
  199.                 .getSystemService(Context.AUDIO_SERVICE);  
  200.   
  201.                 // sound  
  202.                 final boolean useDefaultSound =  
  203.                     (notification.defaults & Notification.DEFAULT_SOUND) != 0;  
  204.                 ///M: log sound information   
  205.                 if (DBG) {  
  206.                     Log.d(TAG,"useDefaultSound="+useDefaultSound);  
  207.                     Log.d(TAG,"notification.sound="+notification.sound);  
  208.                 }  
  209.   
  210.                 Uri soundUri = null;  
  211.                 boolean hasValidSound = false;  
  212.   
  213.                 if (useDefaultSound) {  
  214.                     soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;  
  215.   
  216.                     // check to see if the default notification sound is silent  
  217.                     ContentResolver resolver = mContext.getContentResolver();  
  218.                     hasValidSound = Settings.System.getString(resolver,  
  219.                            Settings.System.NOTIFICATION_SOUND) != null;  
  220.                 } else if (notification.sound != null) {  
  221.                     soundUri = notification.sound;  
  222.                     hasValidSound = (soundUri != null);  
  223.                 }  
  224.   
  225.                 if (hasValidSound) {  
  226.                     boolean looping = (notification.flags & Notification.FLAG_INSISTENT) != 0;  
  227.                     int audioStreamType;  
  228.                     if (notification.audioStreamType >= 0) {  
  229.                         audioStreamType = notification.audioStreamType;  
  230.                     } else {  
  231.                         audioStreamType = DEFAULT_STREAM_TYPE;  
  232.                     }  
  233.                     mSoundNotification = r;  
  234.                     ///M: log sound information  
  235.                     if (DBG) {  
  236.                         Log.d(TAG,"looping="+looping);  
  237.                         Log.d(TAG,"audioStreamType="+audioStreamType);  
  238.                         Log.d(TAG,"StreamVolume="+audioManager.getStreamVolume(audioStreamType));  
  239.                     }  
  240.                     // do not play notifications if stream volume is 0  
  241.                     // (typically because ringer mode is silent) or if speech recognition is active.  
  242.                     if ((audioManager.getStreamVolume(audioStreamType) != 0)  
  243.                             && !audioManager.isSpeechRecognitionActive()) {  
  244.                         final long identity = Binder.clearCallingIdentity();  
  245.                         try {  
  246.                             final IRingtonePlayer player = mAudioService.getRingtonePlayer();  
  247.                             if (player != null) {  
  248.                                 ///M: [ALPS00461691]No notification sound when it detects wifi networks  
  249.                                 if (user.getIdentifier() == UserHandle.USER_ALL) {  
  250.                                     user = UserHandle.OWNER;  
  251.                                 }  
  252.                                 player.playAsync(soundUri, user, looping, audioStreamType);  
  253.                             }  
  254.                         } catch (RemoteException e) {  
  255.                         } finally {  
  256.                             Binder.restoreCallingIdentity(identity);  
  257.                         }  
  258.                     }  
  259.                 }  
  260.   
  261.                 // vibrate  
  262.                 ///M: for device manager   
  263.                 if (DBG) {  
  264.                     Log.d(TAG,"mDmLock="+mDmLock);  
  265.                 }  
  266.                 if (mDmLock == false){  
  267.                 // Does the notification want to specify its own vibration?  
  268.                 final boolean hasCustomVibrate = notification.vibrate != null;  
  269.   
  270.                 // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,  
  271.                 // and no other vibration is specified, we fall back to vibration  
  272.                 final boolean convertSoundToVibration =  
  273.                            !hasCustomVibrate  
  274.                         && hasValidSound  
  275.                         && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);  
  276.   
  277.                 // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.  
  278.                 final boolean useDefaultVibrate =  
  279.                         (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;  
  280.   
  281.                 if ((useDefaultVibrate || convertSoundToVibration || hasCustomVibrate)  
  282.                         && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) {  
  283.                     mVibrateNotification = r;  
  284.   
  285.                     if (DBG) {  
  286.                         Log.w(TAG, "set vibrate!");  
  287.                     }  
  288.   
  289.                     if (useDefaultVibrate || convertSoundToVibration) {  
  290.                         // Escalate privileges so we can use the vibrator even if the notifying app  
  291.                         // does not have the VIBRATE permission.  
  292.                         long identity = Binder.clearCallingIdentity();  
  293.                         try {  
  294.                             mVibrator.vibrate(useDefaultVibrate ? mDefaultVibrationPattern  
  295.                                                                 : mFallbackVibrationPattern,  
  296.                                 ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);  
  297.                         } finally {  
  298.                             Binder.restoreCallingIdentity(identity);  
  299.                         }  
  300.                     } else if (notification.vibrate.length > 1) {  
  301.                         // If you want your own vibration pattern, you need the VIBRATE permission  
  302.                         mVibrator.vibrate(notification.vibrate,  
  303.                             ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);  
  304.                     }  
  305.                 }  
  306.                 } // mDmLock == false  
  307.             }  
  308.   
  309.             // this option doesn't shut off the lights  
  310.   
  311.             // light  
  312.             // the most recent thing gets the light  
  313.             mLights.remove(old);  
  314.             if (mLedNotification == old) {  
  315.                 mLedNotification = null;  
  316.             }  
  317.             //Slog.i(TAG, "notification.lights="  
  318.             //        + ((old.notification.lights.flags & Notification.FLAG_SHOW_LIGHTS) != 0));  
  319.             if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0  
  320.                     && canInterrupt) {  
  321.                 mLights.add(r);  
  322.                 updateLightsLocked();  
  323.             } else {  
  324.                 if (old != null  
  325.                         && ((old.notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0)) {  
  326.                     updateLightsLocked();  
  327.                 }  
  328.             }  
  329.         }  
  330.   
  331.         idOut[0] = id;  
  332.     }  
上面这个方法做的操作有点多,代码有300多行。其中有设计播放声音的地方:

[java]  view plain  copy
 
  1. <span style="font-size:18px;"> player.playAsync(soundUri, user, looping, audioStreamType);</span>  
有是否播放震动的地方:

[java]  view plain  copy
 
  1. mVibrator.vibrate(notification.vibrate,  
  2.                            ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);  
最后闪灯的地方在这个逻辑中:

[java]  view plain  copy
 
  1. if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0  
  2.                    && canInterrupt) {  
  3.                mLights.add(r);  
  4.                updateLightsLocked();  
  5.            }   
重点看updateLightsLocked()这个方法,这个方法里面有逻辑的操作;


       Step 3:updateLightsLocked()这个方法的代码如下:

[java]  view plain  copy
 
  1. // lock on mNotificationList  
  2.     private void updateLightsLocked()  
  3.     {  
  4.         // handle notification lights  
  5.         if (mLedNotification == null) {  
  6.             // get next notification, if any  
  7.             int n = mLights.size();  
  8.             if (n > 0) {  
  9.                 mLedNotification = mLights.get(n-1);  
  10.             }  
  11.         }  
  12.   
  13.         // Don't flash while we are in a call or screen is on  
  14.         ///M: we need flash when screen is on  
  15.         //mScreenOn add by lvmingfei for don't flash while screen is on in 2013-09-20  
  16.         if (mLedNotification == null || mInCall || mCallRinging)) {  
  17.             mNotificationLight.turnOff();  
  18.         } else {  
  19.             int ledARGB = mLedNotification.notification.ledARGB;  
  20.             int ledOnMS = mLedNotification.notification.ledOnMS;  
  21.             int ledOffMS = mLedNotification.notification.ledOffMS;  
  22.             if ((mLedNotification.notification.defaults & Notification.DEFAULT_LIGHTS) != 0) {  
  23.                 ledARGB = mDefaultNotificationColor;  
  24.                 ledOnMS = mDefaultNotificationLedOn;  
  25.                 ledOffMS = mDefaultNotificationLedOff;  
  26.             }  
  27.             if (mNotificationPulseEnabled) {  
  28.                 // pulse repeatedly  
  29.                 ///M: log lights information   
  30.                 Log.d(TAG, "notification setFlashing ledOnMS = "+ledOnMS + " ledOffMS = "+ ledOffMS + ", ledARGB :" + ledARGB);  
  31.                 mNotificationLight.setFlashing(ledARGB, LightsService.LIGHT_FLASH_TIMED,  
  32.                         ledOnMS, ledOffMS);  
  33.                 ///M:   
  34.             } else {  
  35.                 // pulse only once  
  36.                 mNotificationLight.pulse(ledARGB, ledOnMS);  
  37.             }  
  38.         }  
  39.     }  
这段代码中有如下操作,判断一些变量的状态,以决定时候关闭指示灯,还是闪光,还是只闪一次的操作;
电话的状态是否是offhook,或来电的状态,会操作:
[java]  view plain  copy
 
  1. <span style="font-size:18px;">mNotificationLight.turnOff();</span>  
下面这个条件也很重要:
[java]  view plain  copy
 
  1. <span style="font-size:18px;">if ((mLedNotification.notification.defaults & Notification.DEFAULT_LIGHTS) != 0) {</span>  
未解来电,或短信的时候这个值会设置为
[java]  view plain  copy
 
  1. <span style="font-size:18px;">notification.defaults |= Notification.DEFAULT_LIGHTS;</span>  
这个值是4,那么上面的这个判断就为true了,所以灯的颜色就不是由
[java]  view plain  copy
 
  1. <span style="font-size:18px;">mLedNotification.notification.ledARGB;</span>  
这个值决定的了,而是由mDefaultNotificationColor这个值决定的,这个值的定义在

[java]  view plain  copy
 
  1. <span style="font-size:18px;">mDefaultNotificationColor = resources.getColor(  
  2.                 com.android.internal.R.color.config_defaultNotificationColor);</span>  
这个值的定义在framework/base/core/res/res/values/config.xml中定义的,

[java]  view plain  copy
 
  1. <span style="font-size:18px;"><color name="config_defaultNotificationColor">#ff0000ff</color></span>  
这个表示是蓝灯;具体想改成其他值;

  1. #ff0000ff 表示蓝灯
  2. #ff00ff00 表示绿灯
  3. #ffff0000 表示红灯
后面的逻辑就调用到LightsService.java中去了,这个类是管理灯的类,(背光灯,按键灯,指示灯等等);


     拓展:

             如果想实现屏幕亮的时候,指示灯灭,屏幕灭的时候指示灯亮;可以监听ACTION_SCREEN_ON/ACTION_SCREEN_OFF的广播,搞一个全局的变量控制下;再调用updateNotificationPulse()这个方法,把变量的判断加载updateNotificationPulse()这个方法的灯亮灭判断的地方即可;


        其次,我们来看看返回键的灯,即按键灯;

        Step 1 :先来看看PowerManagerService.java这个类。按键灯的定义

[java]  view plain  copy
 
  1. <span style="font-size:18px;"private LightsService.Light mButtonLight;</span>  
        初始化方法:
[java]  view plain  copy
 
  1. <span style="font-size:18px;">mButtonLight = mLightsService.getLight(LightsService.LIGHT_ID_BUTTONS);</span>  
[java]  view plain  copy
 
  1. <span style="font-size:18px;"if ( (newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT) && (mWakefulness == WAKEFULNESS_AWAKE) && !mIPOShutdown && !mShutdownFlag) {  
  2.                 if ( ( (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0 ) ||  
  3.                         ( (mUserActivitySummary & USER_ACTIVITY_BUTTON_BRIGHT) != 0) ) {  
  4.                     mButtonLight.setBrightness(mScreenBrightness);  
  5.                     Slog.i(TAG, "setBrightness mButtonLight, mScreenBrightness=" + mScreenBrightness);  
  6.                 } else {  
  7.                     mButtonLight.turnOff();  
  8.                     Slog.i(TAG, "setBrightness mButtonLight 0 ===.");  
  9.                 }  
  10.             } else {  
  11.                 mButtonLight.turnOff();  
  12.                 Slog.i(TAG, "setBrightness mButtonLight else 0.");  
  13.             }</span>  
灯的点亮的方法setBrightness()

灯关闭的方法turnOff()

要想修改按键灯随p-sensor的灯的亮灭同步,可以参考Android4.2中Phone的P-sensor的应用的分析

然后再加上上述控制灯亮灭的方法就可实现同步;


     总结:灯的亮灭最后都会调用到LightsService.java这个类的,最后通过c代码调用底层的接口实现灯的颜色和闪烁的变化的;

最终通过JNI调用vendor\mediatek\proprietary\hardware\liblights\lights.c

另外三色灯底层是写死的只能三色,要是自定义请修改lights.c


  1. /* Copyright Statement: 
  2.  * 
  3.  * This software/firmware and related documentation ("MediaTek Software") are 
  4.  * protected under relevant copyright laws. The information contained herein is 
  5.  * confidential and proprietary to MediaTek Inc. and/or its licensors. Without 
  6.  * the prior written permission of MediaTek inc. and/or its licensors, any 
  7.  * reproduction, modification, use or disclosure of MediaTek Software, and 
  8.  * information contained herein, in whole or in part, shall be strictly 
  9.  * prohibited. 
  10.  *  
  11.  * MediaTek Inc. (C) 2010. All rights reserved. 
  12.  *  
  13.  * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES 
  14.  * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") 
  15.  * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER 
  16.  * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL 
  17.  * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
  18.  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR 
  19.  * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH 
  20.  * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, 
  21.  * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES 
  22.  * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. 
  23.  * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO 
  24.  * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK 
  25.  * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE 
  26.  * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR 
  27.  * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S 
  28.  * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE 
  29.  * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE 
  30.  * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE 
  31.  * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
  32.  * 
  33.  * The following software/firmware and/or related documentation ("MediaTek 
  34.  * Software") have been modified by MediaTek Inc. All revisions are subject to 
  35.  * any receiver's applicable license agreements with MediaTek Inc. 
  36.  */  
  37.   
  38. /* 
  39.  * Copyright (C) 2008 The Android Open Source Project 
  40.  * 
  41.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  42.  * you may not use this file except in compliance with the License. 
  43.  * You may obtain a copy of the License at 
  44.  * 
  45.  *      http://www.apache.org/licenses/LICENSE-2.0 
  46.  * 
  47.  * Unless required by applicable law or agreed to in writing, software 
  48.  * distributed under the License is distributed on an "AS IS" BASIS, 
  49.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  50.  * See the License for the specific language governing permissions and 
  51.  * limitations under the License. 
  52.  */  
  53.   
  54.   
  55. #define LOG_TAG "lights"  
  56.   
  57.   
  58. #include <cutils/log.h>  
  59.   
  60. #include <stdint.h>  
  61. #include <string.h>  
  62. #include <unistd.h>  
  63. #include <errno.h>  
  64. #include <fcntl.h>  
  65. #include <pthread.h>  
  66. #include <time.h>  
  67.   
  68. #include <sys/ioctl.h>  
  69. #include <sys/types.h>  
  70.   
  71. #include <hardware/lights.h>  
  72.   
  73. #define LIGHTS_DBG_ON  
  74. /******************************************************************************/  
  75.   
  76. static pthread_once_t g_init = PTHREAD_ONCE_INIT;  
  77. static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;  
  78. static int g_haveTrackballLight = 0;  
  79. static struct light_state_t g_notification;  
  80. static struct light_state_t g_battery;  
  81. static int g_backlight = 255;  
  82. static int g_trackball = -1;  
  83. static int g_buttons = 0;  
  84. static int g_attention = 0;  
  85.   
  86. /* TRACKBALL BACKLIGHT */  
  87. char const*const TRACKBALL_FILE  
  88.         = "/sys/class/leds/jogball-backlight/brightness";  
  89.   
  90. /* RED LED */  
  91. char const*const RED_LED_FILE  
  92.         = "/sys/class/leds/red/brightness";  
  93.   
  94. char const*const RED_TRIGGER_FILE  
  95.         = "/sys/class/leds/red/trigger";  
  96.   
  97. char const*const RED_DELAY_ON_FILE  
  98.         = "/sys/class/leds/red/delay_on";  
  99.   
  100. char const*const RED_DELAY_OFF_FILE  
  101.         = "/sys/class/leds/red/delay_off";  
  102.   
  103. /* GREEN LED */  
  104. char const*const GREEN_LED_FILE  
  105.         = "/sys/class/leds/green/brightness";  
  106.   
  107. char const*const GREEN_TRIGGER_FILE  
  108.         = "/sys/class/leds/green/trigger";  
  109.   
  110. char const*const GREEN_DELAY_ON_FILE  
  111.         = "/sys/class/leds/green/delay_on";  
  112.   
  113. char const*const GREEN_DELAY_OFF_FILE  
  114.         = "/sys/class/leds/green/delay_off";  
  115.   
  116. /* BLUE LED */  
  117. char const*const BLUE_LED_FILE  
  118.         = "/sys/class/leds/blue/brightness";  
  119.   
  120. char const*const BLUE_TRIGGER_FILE  
  121.         = "/sys/class/leds/blue/trigger";  
  122.   
  123. char const*const BLUE_DELAY_ON_FILE  
  124.         = "/sys/class/leds/blue/delay_on";  
  125.   
  126. char const*const BLUE_DELAY_OFF_FILE  
  127.         = "/sys/class/leds/blue/delay_off";  
  128.   
  129. /* LCD BACKLIGHT */  
  130. char const*const LCD_FILE  
  131.         = "/sys/class/leds/lcd-backlight/brightness";  
  132.   
  133. /* KEYBOARD BACKLIGHT */  
  134. char const*const KEYBOARD_FILE  
  135.         = "/sys/class/leds/keyboard-backlight/brightness";  
  136.   
  137. /* BUTTON BACKLIGHT */  
  138. char const*const BUTTON_FILE  
  139.         = "/sys/class/leds/button-backlight/brightness";  
  140.   
  141. //ALPS0804285 add for delay  
  142. int led_wait_delay(int ms)   
  143. {  
  144.     struct timespec req = {.tv_sec = 0, .tv_nsec = ms*1000000};  
  145.     struct timespec rem;  
  146.     int ret = nanosleep(&req, &rem);  
  147.   
  148.     while(ret)  
  149.     {  
  150.         if(errno == EINTR)  
  151.         {  
  152.             req.tv_sec  = rem.tv_sec;  
  153.             req.tv_nsec = rem.tv_nsec;  
  154.             ret = nanosleep(&req, &rem);  
  155.         }  
  156.         else  
  157.         {  
  158.             perror("nanosleep");  
  159.             return errno;  
  160.         }  
  161.     }  
  162.     return 0;  
  163. }  
  164.   
  165. /** 
  166.  * device methods 
  167.  */  
  168.   
  169. void init_globals(void)  
  170. {  
  171.     // init the mutex  
  172.     pthread_mutex_init(&g_lock, NULL);  
  173.   
  174.     // figure out if we have the trackball LED or not  
  175.     g_haveTrackballLight = (access(TRACKBALL_FILE, W_OK) == 0) ? 1 : 0;  
  176.   
  177. }  
  178.   
  179. static int  
  180. write_int(char const* path, int value)  
  181. {  
  182.     int fd;  
  183.   
  184. #ifdef LIGHTS_INFO_ON  
  185.     ALOGD("write %d to %s", value, path);  
  186. #endif  
  187.   
  188.     fd = open(path, O_RDWR);  
  189.     ALOGD("write_int open fd=%d\n", fd);  
  190.     if (fd >= 0) {  
  191.         char buffer[20];  
  192.         int bytes = sprintf(buffer, "%d\n", value);  
  193.         int amt = write(fd, buffer, bytes);  
  194.         close(fd);  
  195.         return amt == -1 ? -errno : 0;  
  196.     } else {  
  197.         return -errno;  
  198.     }  
  199. }  
  200.   
  201. static int  
  202. write_str(char const* path, char *str)  
  203. {  
  204.     int fd;  
  205.   
  206. #ifdef LIGHTS_INFO_ON  
  207.     ALOGD("write %s to %s", str, path);  
  208. #endif  
  209.   
  210.     fd = open(path, O_WRONLY);  
  211.     if (fd >= 0) {  
  212.         char buffer[20];  
  213.         int bytes = sprintf(buffer, "%s", str);  
  214.         int amt = write(fd, buffer, bytes);  
  215.         close(fd);  
  216.         return amt == -1 ? -errno : 0;  
  217.     } else {  
  218.         return -errno;  
  219.     }  
  220. }  
  221.   
  222. static int  
  223. is_lit(struct light_state_t const* state)  
  224. {  
  225.     return state->color & 0x00ffffff;  
  226. }  
  227.   
  228. static int  
  229. blink_red(int level, int onMS, int offMS)  
  230. {  
  231.     static int preStatus = 0; // 0: off, 1: blink, 2: no blink  
  232.     int nowStatus;  
  233.     int i = 0;  
  234.   
  235.     if (level == 0)  
  236.         nowStatus = 0;  
  237.     else if (onMS && offMS)  
  238.         nowStatus = 1;  
  239.     else  
  240.         nowStatus = 2;  
  241.   
  242.     if (preStatus == nowStatus)  
  243.         return -1;  
  244.   
  245. #ifdef LIGHTS_DBG_ON  
  246.     ALOGD("blink_red, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);  
  247. #endif  
  248.     if (nowStatus == 0) {  
  249.             write_int(RED_LED_FILE, 0);  
  250.     }  
  251.     else if (nowStatus == 1) {  
  252. //          write_int(RED_LED_FILE, level); // default full brightness  
  253.         write_str(RED_TRIGGER_FILE, "timer");  
  254.         while (((access(RED_DELAY_OFF_FILE, F_OK) == -1) || (access(RED_DELAY_OFF_FILE, R_OK|W_OK) == -1)) && i<10) {  
  255.             ALOGD("RED_DELAY_OFF_FILE doesn't exist or cannot write!!\n");  
  256.             led_wait_delay(5);//sleep 5ms for wait kernel LED class create led delay_off/delay_on node of fs  
  257.             i++;  
  258.         }  
  259.         write_int(RED_DELAY_OFF_FILE, offMS);  
  260.         write_int(RED_DELAY_ON_FILE, onMS);  
  261.     }  
  262.     else {  
  263.         write_str(RED_TRIGGER_FILE, "none");  
  264.             write_int(RED_LED_FILE, 255); // default full brightness  
  265.     }  
  266.   
  267.     preStatus = nowStatus;  
  268.   
  269.     return 0;  
  270. }  
  271.   
  272. static int  
  273. blink_green(int level, int onMS, int offMS)  
  274. {  
  275.     static int preStatus = 0; // 0: off, 1: blink, 2: no blink  
  276.     int nowStatus;  
  277.     int i = 0;  
  278.   
  279.     if (level == 0)  
  280.         nowStatus = 0;  
  281.     else if (onMS && offMS)  
  282.         nowStatus = 1;  
  283.     else  
  284.         nowStatus = 2;  
  285.   
  286.     if (preStatus == nowStatus)  
  287.         return -1;  
  288.   
  289. #ifdef LIGHTS_DBG_ON  
  290.     ALOGD("blink_green, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);  
  291. #endif  
  292.     if (nowStatus == 0) {  
  293.             write_int(GREEN_LED_FILE, 0);  
  294.     }  
  295.     else if (nowStatus == 1) {  
  296. //          write_int(GREEN_LED_FILE, level); // default full brightness  
  297.         write_str(GREEN_TRIGGER_FILE, "timer");  
  298.         while (((access(GREEN_DELAY_OFF_FILE, F_OK) == -1) || (access(GREEN_DELAY_OFF_FILE, R_OK|W_OK) == -1)) && i<10) {  
  299.             ALOGD("GREEN_DELAY_OFF_FILE doesn't exist or cannot write!!\n");  
  300.             led_wait_delay(5);//sleep 5ms for wait kernel LED class create led delay_off/delay_on node of fs  
  301.             i++;  
  302.         }  
  303.         write_int(GREEN_DELAY_OFF_FILE, offMS);  
  304.         write_int(GREEN_DELAY_ON_FILE, onMS);  
  305.     }  
  306.     else {  
  307.         write_str(GREEN_TRIGGER_FILE, "none");  
  308.             write_int(GREEN_LED_FILE, 255); // default full brightness  
  309.     }  
  310.   
  311.     preStatus = nowStatus;  
  312.   
  313.     return 0;  
  314. }  
  315.   
  316. static int  
  317. blink_blue(int level, int onMS, int offMS)  
  318. {  
  319.     static int preStatus = 0; // 0: off, 1: blink, 2: no blink  
  320.     int nowStatus;  
  321.     int i = 0;  
  322.   
  323.     if (level == 0)  
  324.         nowStatus = 0;  
  325.     else if (onMS && offMS)  
  326.         nowStatus = 1;  
  327.     else  
  328.         nowStatus = 2;  
  329.   
  330.     if (preStatus == nowStatus)  
  331.         return -1;  
  332.   
  333. #ifdef LIGHTS_DBG_ON  
  334.     ALOGD("blink_blue, level=%d, onMS=%d, offMS=%d\n", level, onMS, offMS);  
  335. #endif  
  336.     if (nowStatus == 0) {  
  337.             write_int(BLUE_LED_FILE, 0);  
  338.     }  
  339.     else if (nowStatus == 1) {  
  340. //          write_int(BLUE_LED_FILE, level); // default full brightness  
  341.         write_str(BLUE_TRIGGER_FILE, "timer");  
  342.         while (((access(BLUE_DELAY_OFF_FILE, F_OK) == -1) || (access(BLUE_DELAY_OFF_FILE, R_OK|W_OK) == -1)) && i<10) {  
  343.             ALOGD("BLUE_DELAY_OFF_FILE doesn't exist or cannot write!!\n");  
  344.             led_wait_delay(5);//sleep 5ms for wait kernel LED class create led delay_off/delay_on node of fs  
  345.             i++;  
  346.         }  
  347.         write_int(BLUE_DELAY_OFF_FILE, offMS);  
  348.         write_int(BLUE_DELAY_ON_FILE, onMS);  
  349.     }  
  350.     else {  
  351.         write_str(BLUE_TRIGGER_FILE, "none");  
  352.             write_int(BLUE_LED_FILE, 255); // default full brightness  
  353.     }  
  354.   
  355.     preStatus = nowStatus;  
  356.   
  357.     return 0;  
  358. }  
  359.   
  360. static int  
  361. handle_trackball_light_locked(struct light_device_t* dev)  
  362. {  
  363.     int mode = g_attention;  
  364.   
  365.     if (mode == 7 && g_backlight) {  
  366.         mode = 0;  
  367.     }  
  368.     ALOGV("%s g_backlight = %d, mode = %d, g_attention = %d\n",  
  369.         __func__, g_backlight, mode, g_attention);  
  370.   
  371.     // If the value isn't changing, don't set it, because this  
  372.     // can reset the timer on the breathing mode, which looks bad.  
  373.     if (g_trackball == mode) {  
  374.         return 0;  
  375.     }  
  376.   
  377.     return write_int(TRACKBALL_FILE, mode);  
  378. }  
  379.   
  380. static int  
  381. rgb_to_brightness(struct light_state_t const* state)  
  382. {  
  383.     int color = state->color & 0x00ffffff;  
  384.     return ((77*((color>>16)&0x00ff))  
  385.             + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;  
  386. }  
  387.   
  388. static int  
  389. set_light_backlight(struct light_device_t* dev,  
  390.         struct light_state_t const* state)  
  391. {  
  392.     int err = 0;  
  393.     int brightness = rgb_to_brightness(state);  
  394.     pthread_mutex_lock(&g_lock);  
  395.     g_backlight = brightness;  
  396.     err = write_int(LCD_FILE, brightness);  
  397.     if (g_haveTrackballLight) {  
  398.         handle_trackball_light_locked(dev);  
  399.     }  
  400.     pthread_mutex_unlock(&g_lock);  
  401.     return err;  
  402. }  
  403.   
  404. static int  
  405. set_light_keyboard(struct light_device_t* dev,  
  406.         struct light_state_t const* state)  
  407. {  
  408.     int err = 0;  
  409.     int on = is_lit(state);  
  410.     pthread_mutex_lock(&g_lock);  
  411.     err = write_int(KEYBOARD_FILE, on?255:0);  
  412.     pthread_mutex_unlock(&g_lock);  
  413.     return err;  
  414. }  
  415.   
  416. static int  
  417. set_light_buttons(struct light_device_t* dev,  
  418.         struct light_state_t const* state)  
  419. {  
  420.     int err = 0;  
  421.     int on = is_lit(state);  
  422.     pthread_mutex_lock(&g_lock);  
  423.     g_buttons = on;  
  424.     err = write_int(BUTTON_FILE, on?255:0);  
  425.     pthread_mutex_unlock(&g_lock);  
  426.     return err;  
  427. }  
  428.   
  429. static int  
  430. set_speaker_light_locked(struct light_device_t* dev,  
  431.         struct light_state_t const* state)  
  432. {  
  433.     int len;  
  434.     int alpha, red, green, blue;  
  435.     int onMS, offMS;  
  436.     unsigned int colorRGB;  
  437.   
  438.     switch (state->flashMode) {  
  439.         case LIGHT_FLASH_TIMED:  
  440.             onMS = state->flashOnMS;  
  441.             offMS = state->flashOffMS;  
  442.             break;  
  443.         case LIGHT_FLASH_NONE:  
  444.         default:  
  445.             onMS = 0;  
  446.             offMS = 0;  
  447.             break;  
  448.     }  
  449.   
  450.     colorRGB = state->color;  
  451.   
  452. #ifdef LIGHTS_DBG_ON  
  453.     ALOGD("set_led_state colorRGB=%08X, onMS=%d, offMS=%d\n",  
  454.             colorRGB, onMS, offMS);  
  455. #endif  
  456.   
  457.     alpha = (colorRGB >> 24) & 0xFF;  
  458.     if (alpha) {  
  459.         red = (colorRGB >> 16) & 0xFF;  
  460.         green = (colorRGB >> 8) & 0xFF;  
  461.         blue = colorRGB & 0xFF;  
  462.     } else { // alpha = 0 means turn the LED off  
  463.         red = green = blue = 0;  
  464.     }  
  465.   
  466.     if (red) {  
  467.         blink_green(0, 0, 0);  
  468.         blink_blue(0, 0, 0);  
  469.         blink_red(red, onMS, offMS);  
  470.     }  
  471.     else if (green) {  
  472.         blink_red(0, 0, 0);  
  473.         blink_blue(0, 0, 0);  
  474.         blink_green(green, onMS, offMS);  
  475.     }  
  476.     else if (blue) {  
  477.         blink_red(0, 0, 0);  
  478.         blink_green(0, 0, 0);  
  479.         blink_blue(blue, onMS, offMS);  
  480.     }  
  481.     else {  
  482.         blink_red(0, 0, 0);  
  483.         blink_green(0, 0, 0);  
  484.         blink_blue(0, 0, 0);  
  485.     }  
  486.   
  487.     return 0;  
  488. }  
  489.   
  490. static void  
  491. handle_speaker_battery_locked(struct light_device_t* dev)  
  492. {  
  493.     if (is_lit(&g_battery)) {  
  494.         set_speaker_light_locked(dev, &g_battery);  
  495.     } else {  
  496.         set_speaker_light_locked(dev, &g_battery); /*Turkey workaround: notification and Low battery case, IPO bootup, NLED cannot blink*/  
  497.         set_speaker_light_locked(dev, &g_notification);  
  498.     }  
  499. }  
  500.   
  501. static int  
  502. set_light_battery(struct light_device_t* dev,  
  503.         struct light_state_t const* state)  
  504. {  
  505.     pthread_mutex_lock(&g_lock);  
  506.     g_battery = *state;  
  507.     if (g_haveTrackballLight) {  
  508.         set_speaker_light_locked(dev, state);  
  509.     }  
  510.     handle_speaker_battery_locked(dev);  
  511.     pthread_mutex_unlock(&g_lock);  
  512.     return 0;  
  513. }  
  514.   
  515. static int  
  516. set_light_notifications(struct light_device_t* dev,  
  517.         struct light_state_t const* state)  
  518. {  
  519.     pthread_mutex_lock(&g_lock);  
  520.     g_notification = *state;  
  521.     ALOGV("set_light_notifications g_trackball=%d color=0x%08x",  
  522.             g_trackball, state->color);  
  523.     if (g_haveTrackballLight) {  
  524.         handle_trackball_light_locked(dev);  
  525.     }  
  526.     handle_speaker_battery_locked(dev);  
  527.     pthread_mutex_unlock(&g_lock);  
  528.     return 0;  
  529. }  
  530.   
  531. static int  
  532. set_light_attention(struct light_device_t* dev,  
  533.         struct light_state_t const* state)  
  534. {  
  535.     pthread_mutex_lock(&g_lock);  
  536.     ALOGV("set_light_attention g_trackball=%d color=0x%08x",  
  537.             g_trackball, state->color);  
  538.     if (state->flashMode == LIGHT_FLASH_HARDWARE) {  
  539.         g_attention = state->flashOnMS;  
  540.     } else if (state->flashMode == LIGHT_FLASH_NONE) {  
  541.         g_attention = 0;  
  542.     }  
  543.     if (g_haveTrackballLight) {  
  544.         handle_trackball_light_locked(dev);  
  545.     }  
  546.     pthread_mutex_unlock(&g_lock);  
  547.     return 0;  
  548. }  
  549.   
  550.   
  551. /** Close the lights device */  
  552. static int  
  553. close_lights(struct light_device_t *dev)  
  554. {  
  555.     if (dev) {  
  556.         free(dev);  
  557.     }  
  558.     return 0;  
  559. }  
  560.   
  561.   
  562. /******************************************************************************/  
  563.   
  564. /** 
  565.  * module methods 
  566.  */  
  567.   
  568. /** Open a new instance of a lights device using name */  
  569. static int open_lights(const struct hw_module_t* module, char const* name,  
  570.         struct hw_device_t** device)  
  571. {  
  572.     int (*set_light)(struct light_device_t* dev,  
  573.             struct light_state_t const* state);  
  574.   
  575.     if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) {  
  576.         set_light = set_light_backlight;  
  577.     }  
  578.     else if (0 == strcmp(LIGHT_ID_KEYBOARD, name)) {  
  579.         set_light = set_light_keyboard;  
  580.     }  
  581.     else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {  
  582.         set_light = set_light_buttons;  
  583.     }  
  584.     else if (0 == strcmp(LIGHT_ID_BATTERY, name)) {  
  585.         set_light = set_light_battery;  
  586.     }  
  587.     else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {  
  588.         set_light = set_light_notifications;  
  589.     }  
  590.     else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) {  
  591.         set_light = set_light_attention;  
  592.     }  
  593.     else {  
  594.         return -EINVAL;  
  595.     }  
  596.   
  597.     pthread_once(&g_init, init_globals);  
  598.   
  599.     struct light_device_t *dev = malloc(sizeof(struct light_device_t));  
  600.     memset(dev, 0, sizeof(*dev));  
  601.   
  602.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  603.     dev->common.version = 0;  
  604.     dev->common.module = (struct hw_module_t*)module;  
  605.     dev->common.close = (int (*)(struct hw_device_t*))close_lights;  
  606.     dev->set_light = set_light;  
  607.   
  608.     *device = (struct hw_device_t*)dev;  
  609.     return 0;  
  610. }  
  611.   
  612.   
  613. static struct hw_module_methods_t lights_module_methods = {  
  614.     .open =  open_lights,  
  615. };  
  616.   
  617. /* 
  618.  * The lights Module 
  619.  */  
  620. struct hw_module_t HAL_MODULE_INFO_SYM = {  
  621.     .tag = HARDWARE_MODULE_TAG,  
  622.     //.version_major = 1,  
  623.     //.version_minor = 0,  
  624.     .id = LIGHTS_HARDWARE_MODULE_ID,  
  625.     .name = "MTK lights Module",  
  626.     .author = "MediaTek",  
  627.     .methods = &lights_module_methods,  
  628. };  


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值