MTK 6.0 充電Led燈分析

最近客戶對(duì)Led這塊增加了很多定制坑匠。所以修改定制完成之后做了總結(jié),順便分析下流程

1. 啟動(dòng)BatteryService

電池的信息擅羞,電壓,溫度义图,充電狀態(tài)等等减俏,都是由BatteryService來提供的。BatteryService是跑在system_process當(dāng)中碱工,在系統(tǒng)初始化的時(shí)候啟動(dòng)娃承,如下 在SystemServer.java中可以看到啟動(dòng)BatteryService的代碼

電池的信息,電壓痛垛,溫度草慧,充電狀態(tài)等等.這些值都是通過節(jié)點(diǎn)獲取的

/sys/class/power_supply/ac/online //AC 電源連接狀態(tài) 交流電 即電源插座


/sys/class/power_supply/usb/online //USB電源連接狀態(tài)


/sys/class/power_supply/battery/status //充電狀態(tài)


/sys/class/power_supply/battery/health //電池狀態(tài)


/sys/class/power_supply/battery/present //使用狀態(tài)


/sys/class/power_supply/battery/capacity //電池 level


/sys/class/power_supply/battery/batt_vol //電池電壓


/sys/class/power_supply/battery/batt_temp //電池溫度


/sys/class/power_supply/battery/technology //電池技術(shù)

/**
     * Starts some essential services that are not tangled up in the bootstrap process.
     */
    private void startCoreServices() {
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);//啟動(dòng)BatteryService
        // Tracks application usage stats.
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
               LocalServices.getService(UsageStatsManagerInternal.class));
        // Update after UsageStatsService is available, needed before performBootDexOpt.
        mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        mSystemServiceManager.startService(WebViewUpdateService.class);
    }

BattryService.java

構(gòu)造函數(shù)做初始化

public BatteryService(Context context) {
        super(context);

        mContext = context;
        mHandler = new Handler(true /*async*/);
        mLed = new Led(context, getLocalService(LightsManager.class));//初始化Ligths
        mBatteryStats = BatteryStatsService.getService();

        mCriticalBatteryLevel = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_criticalBatteryWarningLevel);
        mLowBatteryWarningLevel = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryWarningLevel);
        mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
        mShutdownBatteryTemperature = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shutdownBatteryTemperature);

        // watch for invalid charger messages if the invalid_charger switch exists
        if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {   /// 監(jiān)控終端是否連接不匹配的充電器
            mInvalidChargerObserver.startObserving(
                    "DEVPATH=/devices/virtual/switch/invalid_charger");   ; 
        }
    }

注冊(cè)電池監(jiān)聽

    @Override
    public void onStart() {
        IBinder b = ServiceManager.getService("batteryproperties");
        final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
                IBatteryPropertiesRegistrar.Stub.asInterface(b);
        try {
            //電池監(jiān)聽匙头,注冊(cè)到底層漫谷。當(dāng)?shù)讓与娏扛淖儠?huì)調(diào)用此監(jiān)聽。然后執(zhí)行update 
            //這個(gè)真的騷蹂析, java 和c++ 直接通過binder 進(jìn)行通訊
          //想研究的可以看看這個(gè)大牛 https://blog.csdn.net/zvivi521/article/details/14520883
            batteryPropertiesRegistrar.registerListener(new BatteryListener());
        } catch (RemoteException e) {
            // Should never happen.
        }

        publishBinderService("battery", new BinderService());
        publishLocalService(BatteryManagerInternal.class, new LocalService());//將本地接口publish出去舔示。
    }

    private final class BatteryListener extends IBatteryPropertiesListener.Stub {
        @Override
        public void batteryPropertiesChanged(BatteryProperties props) {
            final long identity = Binder.clearCallingIdentity();
            try {
                BatteryService.this.update(props);//調(diào)用 update()方法,來更新電池的信息數(shù)據(jù)
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
       }
    }

    //將本地接口publish出去电抚。
    private final class LocalService extends BatteryManagerInternal {
        @Override
        public boolean isPowered(int plugTypeSet) {
            synchronized (mLock) {
                return isPoweredLocked(plugTypeSet);
            }
        }

        @Override
        public int getPlugType() {
            synchronized (mLock) {
                return mPlugType;
            }
        }

        @Override
        public int getBatteryLevel() {
            synchronized (mLock) {
                return mBatteryProps.batteryLevel;
            }
        }

        @Override
        public boolean getBatteryLevelLow() {
            synchronized (mLock) {
                return mBatteryLevelLow;
            }
        }

        @Override
        public int getInvalidCharger() {
            synchronized (mLock) {
                return mInvalidCharger;
            }
        }
    }


    //當(dāng)?shù)讓佑行畔⑸蟻硖璧荆瑫?huì)調(diào)用update函數(shù)更新BatteryService中的狀態(tài)值.

    private void update(BatteryProperties props) {
        synchronized (mLock) {
            if (!mUpdatesStopped) {
                mBatteryProps = props;
                if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
                    if (mIPOShutdown)
                        return;
                }
                // Process the new values.
                if (mBootCompleted)
                processValuesLocked(false);
            } else {
                mLastBatteryProps.set(props);
            }
        }
    }

接下來分析主函數(shù)processValuesLocked


    private void processValuesLocked(boolean force) {
        boolean logOutlier = false;
        long dischargeDuration = 0;

        mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
        if (mBatteryProps.chargerAcOnline) {   //檢測(cè)電池充電的方式
            mPlugType = BatteryManager.BATTERY_PLUGGED_AC;    
        } else if (mBatteryProps.chargerUsbOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
        } else if (mBatteryProps.chargerWirelessOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
        } else {
            mPlugType = BATTERY_PLUGGED_NONE;
        }

        /// M: Add for DUAL_INPUT_CHARGER_SUPPORT @{
        if (SystemProperties.get("ro.mtk_diso_support").equals("true")) {
            if (mBatteryProps.chargerAcOnline && mBatteryProps.chargerUsbOnline) {
                mPlugType = BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB;
            }
        }
        /// M: @}

        if (DEBUG) {
            Slog.d(TAG, "Processing new values: "
                    + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
                    + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
                    + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
                    + ", batteryStatus=" + mBatteryProps.batteryStatus
                    + ", batteryHealth=" + mBatteryProps.batteryHealth
                    + ", batteryPresent=" + mBatteryProps.batteryPresent
                    + ", batteryLevel=" + mBatteryProps.batteryLevel
                    + ", batteryTechnology=" + mBatteryProps.batteryTechnology
                    + ", batteryVoltage=" + mBatteryProps.batteryVoltage
                    + ", batteryTemperature=" + mBatteryProps.batteryTemperature
                    + ", mBatteryLevelCritical=" + mBatteryLevelCritical
                    + ", mPlugType=" + mPlugType);
        }
    if (mLastBatteryVoltage != mBatteryProps.batteryVoltage) {
        Log.d(TAG, "mBatteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryLevel=" + mBatteryProps.batteryLevel_smb);
    }
        // Update the battery LED
        mLed.updateLightsLocked();  //更新LED 狀態(tài)

        // Let the battery stats keep track of the current level.
        try {
            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
                    mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
                    mBatteryProps.batteryVoltage);   //更新電池的數(shù)據(jù)
        } catch (RemoteException e) {
            // Should never happen.
        }

        shutdownIfNoPowerLocked();   //沒電了
        shutdownIfOverTempLocked(); //電池溫度過高

        if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus ||
                mBatteryProps.batteryStatus_smb != mLastBatteryStatus_smb ||
                mBatteryProps.batteryHealth != mLastBatteryHealth ||
                mBatteryProps.batteryPresent != mLastBatteryPresent ||
        mBatteryProps.batteryPresent_smb != mLastBatteryPresent_smb ||
                mBatteryProps.batteryLevel != mLastBatteryLevel ||
        mBatteryProps.batteryLevel_smb != mLastBatteryLevel_smb ||
                mPlugType != mLastPlugType ||
                mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
                mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
                mInvalidCharger != mLastInvalidCharger)) {

            if (mPlugType != mLastPlugType) {
                if (mLastPlugType == BATTERY_PLUGGED_NONE) { 
                    // discharging -> charging  // 沒充電到充電

                    // There's no value in this data unless we've discharged at least once and the
                    // battery level has changed; so don't log until it does.
                    if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
                        dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                        logOutlier = true;
                        EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
                                mDischargeStartLevel, mBatteryProps.batteryLevel);
                        // make sure we see a discharge event before logging again
                        mDischargeStartTime = 0;
                    }
                } else if (mPlugType == BATTERY_PLUGGED_NONE) {  
                    // charging -> discharging or we just powered up   //  剛開始充電到或者剛開始放電狀態(tài)
                    mDischargeStartTime = SystemClock.elapsedRealtime();
                    mDischargeStartLevel = mBatteryProps.batteryLevel;
                }
            }
            if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
                    mBatteryProps.batteryHealth != mLastBatteryHealth ||
                    mBatteryProps.batteryPresent != mLastBatteryPresent ||
                    mPlugType != mLastPlugType) {
                EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
                        mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
                        mPlugType, mBatteryProps.batteryTechnology);
            }
            if (mBatteryProps.batteryLevel != mLastBatteryLevel) {  
                // Don't do this just from voltage or temperature changes, that is
                // too noisy.
                EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
                        mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
            }
            if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
                    mPlugType == BATTERY_PLUGGED_NONE) {
                // We want to make sure we log discharge cycle outliers
                // if the battery is about to die.
                dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                logOutlier = true;
            }

            if (!mBatteryLevelLow) {
                // Should we now switch in to low battery mode?   
                if (mPlugType == BATTERY_PLUGGED_NONE
                        && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) {    //檢測(cè)電池電量,是否切換到低電模式蝙叛、俺祠、mLowBatteryWarningLevel//低電閥值 // 
                    mBatteryLevelLow = true;
                }
            } else {
                // Should we now switch out of low battery mode?
                if (mPlugType != BATTERY_PLUGGED_NONE) {
                    mBatteryLevelLow = false;
                } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel)  {
                    mBatteryLevelLow = false;
                } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) {
                    // If being forced, the previous state doesn't matter, we will just
                    // absolutely check to see if we are now above the warning level.
                    mBatteryLevelLow = false;
                }
            }

            sendIntentLocked();  //發(fā)送電池狀態(tài)廣播

            // Separate broadcast is sent for power connected / not connected
            // since the standard intent will not wake any applications and some
            // applications may want to have smart behavior based on this.
            if (mPlugType != 0 && mLastPlugType == 0) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }
            else if (mPlugType == 0 && mLastPlugType != 0) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }

            if (shouldSendBatteryLowLocked()) {
                mSentLowBatteryBroadcast = true;
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) {
                mSentLowBatteryBroadcast = false;
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
                        statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
                        mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                    }
                });
            }

            if (mBatteryProps.batteryStatus != mLastBatteryStatus &&
                    mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CMD_DISCHARGING) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                    final String ACTION_IGNORE_DATA_USAGE_ALERT =
                    "android.intent.action.IGNORE_DATA_USAGE_ALERT";

                    Log.d(TAG, "sendBroadcast ACTION_IGNORE_DATA_USAGE_ALERT");
                    Intent statusIntent = new Intent(ACTION_IGNORE_DATA_USAGE_ALERT);
                    statusIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                    mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
                }
            });
            }

            // Update the battery LED
            // mLed.updateLightsLocked();   

            // This needs to be done after sendIntent() so that we get the lastest battery stats.
            if (logOutlier && dischargeDuration != 0) {
                logOutlierLocked(dischargeDuration);
            }

            mLastBatteryStatus = mBatteryProps.batteryStatus;
            mLastBatteryStatus_smb = mBatteryProps.batteryStatus_smb;
            mLastBatteryHealth = mBatteryProps.batteryHealth;
            mLastBatteryPresent = mBatteryProps.batteryPresent;
            mLastBatteryPresent_smb = mBatteryProps.batteryPresent_smb;
            mLastBatteryLevel = mBatteryProps.batteryLevel;
            mLastBatteryLevel_smb = mBatteryProps.batteryLevel_smb;
            mLastPlugType = mPlugType;
            mLastBatteryVoltage = mBatteryProps.batteryVoltage;
            mLastBatteryTemperature = mBatteryProps.batteryTemperature;
            mLastBatteryLevelCritical = mBatteryLevelCritical;
            mLastInvalidCharger = mInvalidCharger;
        }
    }

sendIntentLocked() 將電池狀態(tài)發(fā)送出去, 應(yīng)用監(jiān)聽廣播即可獲取電池狀態(tài)

    private void sendIntentLocked() {
        //  Pack up the values and broadcast them to everyone
        final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);

        int icon = getIconLocked(mBatteryProps.batteryLevel);

        intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
    intent.putExtra(BatteryManager.EXTRA_STATUS_SMARTBOOK, mBatteryProps.batteryStatus_smb);
        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
    intent.putExtra(BatteryManager.EXTRA_PRESENT_SMARTBOOK, mBatteryProps.batteryPresent_smb);
        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
    intent.putExtra(BatteryManager.EXTRA_LEVEL_SMARTBOOK, mBatteryProps.batteryLevel_smb);
        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
        intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);

        if (DEBUG) {
            Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED.  level:" + mBatteryProps.batteryLevel +
                    ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
                    ", health:" + mBatteryProps.batteryHealth +  ", present:" + mBatteryProps.batteryPresent +
                    ", voltage: " + mBatteryProps.batteryVoltage +
                    ", temperature: " + mBatteryProps.batteryTemperature +
                    ", technology: " + mBatteryProps.batteryTechnology +
                    ", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline +
                    ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
                    ", icon:" + icon  + ", invalid charger:" + mInvalidCharger +
            ", status_smb:" + mBatteryProps.batteryStatus_smb + ", present_smb:" +
                    mBatteryProps.batteryPresent_smb + ",level_smb:" + mBatteryProps.batteryLevel_smb);
        }

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
            }
        });
    

updateLightsLocked() led燈最主要方法

private final class Led {
        private final Light mBatteryLight;

        private final int mBatteryLowARGB;
        private final int mBatteryMediumARGB;
        private final int mBatteryFullARGB;
        private final int mBatteryLedOn;
        private final int mBatteryLedOff;

        public Led(Context context, LightsManager lights) {
            mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);//mBatteryLight,通過LightsManager獲取是那種燈,還有優(yōu)先級(jí)蜘渣,優(yōu)先級(jí)就分為電池和通知

            mBatteryLowARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLowARGB);
            mBatteryMediumARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
            mBatteryFullARGB = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryFullARGB);
            mBatteryLedOn = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLedOn);
            mBatteryLedOff = context.getResources().getInteger(
                    com.android.internal.R.integer.config_notificationsBatteryLedOff);
        }

        /**
         * Synchronize on BatteryService.
         */
        public void updateLightsLocked() {
            final int level = mBatteryProps.batteryLevel;
            final int status = mBatteryProps.batteryStatus;
            if (mIPOBoot)
            {
                //Get led status in IPO mode
                getIpoLedStatus();
            }
            if (level < mLowBatteryWarningLevel) {   // 檢測(cè)當(dāng)前電池狀態(tài)是否為低電亮
                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {  //是低電量淌铐,并且是充電狀態(tài),亮燈
                    updateLedStatus();
                    // Solid red when battery is charging
                    mBatteryLight.setColor(mBatteryLowARGB);//優(yōu)先級(jí)最高蔫缸,mBatteryLowARGB設(shè)置充電Led等的顏色腿准。
                } else {                    
                    LowLevelFlag = true;
                    updateLedStatus();  //更新Led 狀態(tài) 
                    /*chc Flashing red change normally on yellow*/

                    // Flash red when battery is low and not charging
                    // mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
                    //         mBatteryLedOn, mBatteryLedOff);    //低電led模式,閃爍拾碌,
                      mBatteryLight.setFlashing(0xFFFFFF00, Light.LIGHT_FLASH_TIMED,
                            0, 0); //chc edit to yellow
                }
            } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status == BatteryManager.BATTERY_STATUS_FULL) {//充電狀態(tài)
                if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) { //電池電量>90
                    updateLedStatus();
                    // Solid green when full or charging and nearly full
                    mBatteryLight.setColor(mBatteryFullARGB); //設(shè)置Led顏色吐葱。config.xml可以控制
                } else {
                    updateLedStatus();
                    // Solid orange when charging and halfway full
                    mBatteryLight.setColor(mBatteryMediumARGB);
                }
            } else {
                if (ipo_led_on && mIPOBoot) {
                    if (status == BatteryManager.BATTERY_STATUS_FULL || level >= 90) {
                        mBatteryLight.setColor(mBatteryFullARGB);
                    }
                    else {
                        mBatteryLight.setColor(mBatteryMediumARGB);
                    }
                    mIPOBoot = false;
                    ipo_led_on = false;
                }
                // No lights if not charging and not low
                mBatteryLight.turnOff();
            }
        }
        private void getIpoLedStatus() {
            if ("1".equals(SystemProperties.get("sys.ipo.ledon"))) {
                ipo_led_on = true;
            }
            else if ("0".equals(SystemProperties.get("sys.ipo.ledon"))) {
                ipo_led_off = true;
            }
            if (DEBUG) {
                Slog.d(TAG, ">>>>>>>getIpoLedStatus ipo_led_on = " + ipo_led_on + ",  ipo_led_off = " + ipo_led_off + "<<<<<<<");
            }
        }

        private void updateLedStatus() {
            // if LowBatteryWarning happened, we refresh the led state no matter ipo_led is on or off.
            if ((ipo_led_off && mIPOBoot) || (LowLevelFlag && mIPOBoot)) {
                mBatteryLight.turnOff();
                mIPOBoot = false;
                ipo_led_off = false;
                ipo_led_on = false;
                if (DEBUG) {
                    Slog.d(TAG, ">>>>>>>updateLedStatus  LowLevelFlag = " + LowLevelFlag + "<<<<<<<");
                }
            }
        }
    }

接下來分析下(6.0)Led應(yīng)用層設(shè)置。

            manager = (NotificationManager) this
                .getSystemService(NOTIFICATION_SERVICE);
          NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
        notification=mBuilder.build();
        notification.ledARGB = 0xFFFFFF00;
        notification.icon=R.drawable.ic_launcher;
        notification.ledOnMS = 200;
        notification.ledOffMS = 400;                
        notification.flags = Notification.FLAG_SHOW_LIGHTS;
            manager.notify(0, notification);        

應(yīng)用層是通過notification進(jìn)行控制led燈的

NotificationManager.java

public void notify(String tag, int id, Notification notification)
    {
        int[] idOut = new int[1];
        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
        if (notification.sound != null) {
            notification.sound = notification.sound.getCanonicalUri();
            if (StrictMode.vmFileUriExposureEnabled()) {
                notification.sound.checkFileUriExposed("Notification.sound");
            }
        }
        fixLegacySmallIcon(notification, pkg);
        if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { //判斷目標(biāo)SDK版本 6.0必須有icon
            if (notification.getSmallIcon() == null) {
                throw new IllegalArgumentException("Invalid notification (no valid small icon): "
                    + notification);
            }
        }
        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
        Notification stripped = notification.clone();
        Builder.stripForDelivery(stripped);
        try {
            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                    stripped, idOut, UserHandle.myUserId());
            if (id != idOut[0]) {
                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
            }
        } catch (RemoteException e) {
        }
    }

NotificationManagerService.java

 @Override
        public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
                Notification notification, int[] idOut, int userId) throws RemoteException {
            enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
                    Binder.getCallingPid(), tag, id, notification, idOut, userId);
        }



    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
            final int callingPid, final String tag, final int id, final Notification notification,
            int[] idOut, int incomingUserId) {
     
    ....在這里對(duì)mNotificationList通知消息隊(duì)列各條通知的優(yōu)先級(jí)校翔,聲音進(jìn)行了相關(guān)操     
  //然后調(diào)用
   buzzBeepBlinkLocked(r)
   
....
  buzzBeepBlinkLocked(r){
   if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThreshold) {
            mLights.add(record.getKey());
            updateLightsLocked();  //led燈主要操作
            if (mUseAttentionLight) {
                mAttentionLight.pulse();
            }
            blink = true;
        } else if (wasShowLights) {
            updateLightsLocked();
        }
 
}


    // lock on mNotificationList
    void updateLightsLocked()
    {
        // handle notification lights
        NotificationRecord ledNotification = null;
        while (ledNotification == null && !mLights.isEmpty()) {
            final String owner = mLights.get(mLights.size() - 1);
            ledNotification = mNotificationsByKey.get(owner);
            if (ledNotification == null) {
                Slog.wtfStack(TAG, "LED Notification does not exist: " + owner);
                mLights.remove(owner);
            }
        }

        // Don't flash while we are in a call or screen is on
        // if (mLedNotification == null || mInCall || mScreenOn) {
        /// M: Add DM/PPL lock related.
        
        //Cuihangchao removed incall state for zed3
        if (ledNotification == null /*|| mInCall || mScreenOn */|| mDmLock || mPplLock) {    //判斷l(xiāng)ed等什么時(shí)候關(guān)閉弟跑。打電話中,屏幕關(guān)閉時(shí)候等
            mNotificationLight.turnOff();
            mStatusBar.notificationLightOff();
            Log.d("Cuihangchao","color0");
        } else {
            Log.d("Cuihangchao","color1");
            final Notification ledno = ledNotification.sbn.getNotification();
            int ledARGB = ledno.ledARGB;
            int ledOnMS = ledno.ledOnMS;
            int ledOffMS = ledno.ledOffMS;
            if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) {
                Log.d("Cuihangchao","color2");
               // ledARGB = mDefaultNotificationColor;
                ledOnMS = mDefaultNotificationLedOn;
                ledOffMS = mDefaultNotificationLedOff;
            }
            if (mNotificationPulseEnabled) {
                Log.d("Cuihangchao","color4="+ledARGB);
                // pulse repeatedly
                mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,
                        ledOnMS, ledOffMS);  //此處設(shè)置led燈
            }
            // let SystemUI make an independent decision
            //mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
        }
    }

LightsService.java(設(shè)置屏幕亮度展融,鍵盤背光相關(guān)都在里面)


        private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
            if (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS) {
                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                        + Integer.toHexString(color));
                mColor = color;
                mMode = mode;
                mOnMS = onMS;
                mOffMS = offMS;
                Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
                        + Integer.toHexString(color) + ")");
                try {
                    setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);  //通過JNI進(jìn)行設(shè)置
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
                }
            }
        }

com_android_server_lights_LightsService.cpp

static void setLight_native(JNIEnv* /* env */, jobject /* clazz */, jlong ptr,
        jint light, jint colorARGB, jint flashMode, jint onMS, jint offMS, jint brightnessMode)
{
    Devices* devices = (Devices*)ptr;
    light_state_t state;

    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
        return ;
    }

    memset(&state, 0, sizeof(light_state_t));
    state.color = colorARGB;
    state.flashMode = flashMode;
    state.flashOnMS = onMS;
    state.flashOffMS = offMS;
    state.brightnessMode = brightnessMode;

    {
        ALOGD_IF_SLOW(50, "Excessive delay setting light");
        devices->lights[light]->set_light(devices->lights[light], &state);  //通過lights 節(jié)點(diǎn) 進(jìn)行設(shè)置  
    }
}

最后通過hardware檢測(cè)此節(jié)點(diǎn)進(jìn)行相應(yīng)設(shè)置等顏色的窖认,相關(guān)代碼
lights.c(vendor/Mediatek/Proprietary/Hardware/Liblights)
以上文件都在Frameworks下面就不一 一的貼路徑了
此文到此結(jié)束,如發(fā)現(xiàn)有錯(cuò)誤告希,請(qǐng)指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扑浸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子燕偶,更是在濱河造成了極大的恐慌喝噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件指么,死亡現(xiàn)場離奇詭異酝惧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伯诬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門晚唇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盗似,你說我怎么就攤上這事哩陕。” “怎么了赫舒?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵悍及,是天一觀的道長。 經(jīng)常有香客問我接癌,道長心赶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任缺猛,我火速辦了婚禮缨叫,結(jié)果婚禮上椭符,老公的妹妹穿的比我還像新娘。我一直安慰自己弯汰,他們只是感情好艰山,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布湖雹。 她就那樣靜靜地躺著咏闪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摔吏。 梳的紋絲不亂的頭發(fā)上鸽嫂,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音征讲,去河邊找鬼据某。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诗箍,可吹牛的內(nèi)容都是我干的癣籽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滤祖,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼筷狼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起匠童,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤埂材,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后汤求,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俏险,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年扬绪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竖独。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挤牛,死狀恐怖莹痢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赊颠,我是刑警寧澤格二,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站竣蹦,受9級(jí)特大地震影響顶猜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痘括,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一长窄、第九天 我趴在偏房一處隱蔽的房頂上張望滔吠。 院中可真熱鬧,春花似錦挠日、人聲如沸疮绷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冬骚。三九已至,卻和暖如春懂算,著一層夾襖步出監(jiān)牢的瞬間只冻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工计技, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喜德,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓垮媒,卻偏偏與公主長得像舍悯,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子睡雇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,139評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理萌衬,服務(wù)發(fā)現(xiàn),斷路器入桂,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • -「唉奄薇?你不早說,我和你男朋友也只是玩玩而已抗愁,你千萬別當(dāng)真澳俚佟:)」 事情是這樣的。 我有一個(gè)同學(xué)蜘腌,有次和她逛街沫屡,正...
    藍(lán)天作鏡閱讀 430評(píng)論 0 0
  • 今天早上起來后特意去吃了早餐,和洋去的撮珠,老發(fā)和蘭哥沒有去沮脖。早餐帶回了寢室吃,喝豆?jié){把舌頭給燙到了芯急。要死勺届,現(xiàn)...
    天空藍(lán)上閱讀 123評(píng)論 0 0