Settings中电池选项-Android13
Settings中电池选项-Android13
- 1、设置中界面
- 2、电池计算
- 2.1 充电时间计算
- 2.1.1 BatteryUsageStats获取
- 2.1.2 BatteryStatsImpl计算
 
- 2.2 电池剩余使用时间
- 2.2.1 Estimate获取
- 2.2.2 BatteryStatsImpl计算
 
 
- 3、电池信息来源
- 4、命令模拟
- * 日志
 
[电池]Android 9.0 电池未充电与充电字符串提示信息[通俗易懂]
1、设置中界面
packages/apps/Settings/src/com/android/settings/fuelgauge/PowerUsageSummary.java
packages/apps/Settings/res/xml/power_usage_summary.xml
packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java
packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryInfo.java

12-23 13:13:23.184   602   715 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cmp=com.android.settings/.SubSettings (has extras)} from uid 1000
12-23 13:13:23.285   994  2135 D BatteryTipLoader: BatteryInfoLoader post query: 5ms
12-23 13:13:23.356   994  2135 D BatteryInfo: time for getBatteryInfo: 1ms
12-23 13:13:23.357   994  2135 D BatteryTipLoader: BatteryInfoLoader.loadInBackground: 82ms
12-23 13:13:23.950   994   994 D SettingsActivity: Switching to fragment com.android.settings.fuelgauge.batteryusage.PowerUsageSummary
2、电池计算
packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryInfo.java
    public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,@NonNull BatteryUsageStats batteryUsageStats, Estimate estimate,long elapsedRealtimeUs, boolean shortString) {final long startTime = System.currentTimeMillis();final boolean isCompactStatus = context.getResources().getBoolean(com.android.settings.R.bool.config_use_compact_battery_status);BatteryInfo info = new BatteryInfo();info.mBatteryUsageStats = batteryUsageStats;info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;info.averageTimeToDischarge = estimate.getAverageDischargeTime();info.isOverheated = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN)== BatteryManager.BATTERY_HEALTH_OVERHEAT;info.statusLabel = Utils.getBatteryStatus(context, batteryBroadcast, isCompactStatus);info.batteryStatus = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);if (!info.mCharging) {updateBatteryInfoDischarging(context, shortString, estimate, info);} else {updateBatteryInfoCharging(context, batteryBroadcast, batteryUsageStats,info, isCompactStatus);}BatteryUtils.logRuntime(LOG_TAG, "time for getBatteryInfo", startTime);return info;}private static void updateBatteryInfoCharging(Context context, Intent batteryBroadcast,BatteryUsageStats stats, BatteryInfo info, boolean compactStatus) {final Resources resources = context.getResources();final long chargeTimeMs = stats.getChargeTimeRemainingMs();final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,BatteryManager.BATTERY_STATUS_UNKNOWN);info.discharging = false;info.suggestionLabel = null;if (info.isOverheated && status != BatteryManager.BATTERY_STATUS_FULL) {info.remainingLabel = null;int chargingLimitedResId = R.string.power_charging_limited;info.chargeLabel =context.getString(chargingLimitedResId, info.batteryPercentString);} else if (chargeTimeMs > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs);final CharSequence timeString = StringUtil.formatElapsedTime(context,PowerUtil.convertUsToMs(info.remainingTimeUs),false /* withSeconds */,true /* collapseTimeUnit */);int resId = R.string.power_charging_duration;info.remainingLabel = context.getString(R.string.power_remaining_charging_duration_only, timeString);info.chargeLabel = context.getString(resId, info.batteryPercentString, timeString);} else {final String chargeStatusLabel =Utils.getBatteryStatus(context, batteryBroadcast, compactStatus);info.remainingLabel = null;info.chargeLabel = info.batteryLevel == 100 ? info.batteryPercentString :resources.getString(R.string.power_charging, info.batteryPercentString,chargeStatusLabel.toLowerCase());}}private static void updateBatteryInfoDischarging(Context context, boolean shortString,Estimate estimate, BatteryInfo info) {final long drainTimeUs = PowerUtil.convertMsToUs(estimate.getEstimateMillis());if (drainTimeUs > 0) {info.remainingTimeUs = drainTimeUs;info.remainingLabel = PowerUtil.getBatteryRemainingStringFormatted(context,PowerUtil.convertUsToMs(drainTimeUs),null /* percentageString */,false /* basedOnUsage */);info.chargeLabel = PowerUtil.getBatteryRemainingStringFormatted(context,PowerUtil.convertUsToMs(drainTimeUs),info.batteryPercentString,estimate.isBasedOnUsage() && !shortString);info.suggestionLabel = PowerUtil.getBatteryTipStringFormatted(context, PowerUtil.convertUsToMs(drainTimeUs));} else {info.remainingLabel = null;info.suggestionLabel = null;info.chargeLabel = info.batteryPercentString;}}
2.1 充电时间计算
2.1.1 BatteryUsageStats获取
updateBatteryInfoCharging中获取BatteryUsageStats中mChargeTimeRemainingMs还需的充电时间;显示<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string>
BatteryUsageStats对象是BatteryStatsService通过BatteryUsageStatsProvider获取
BatteryUsageStatsProvider中BatteryChargeCalculator.java#calculate最终调用到batteryStats.computeChargeTimeRemaining(rawRealtimeUs)计算
packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java
    public BatteryInfo getBatteryInfo(final String tag) {final BatteryStatsManager systemService = mContext.getSystemService(BatteryStatsManager.class);BatteryUsageStats batteryUsageStats;try {batteryUsageStats = systemService.getBatteryUsageStats(new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());} catch (RuntimeException e) {Log.e(TAG, "getBatteryInfo() error from getBatteryUsageStats()", e);// Use default BatteryUsageStats.batteryUsageStats = new BatteryUsageStats.Builder(new String[0]).build();}final long startTime = System.currentTimeMillis();// Stuff we always need to get BatteryInfofinal Intent batteryBroadcast = mContext.registerReceiver(null,new IntentFilter(Intent.ACTION_BATTERY_CHANGED));final long elapsedRealtimeUs = PowerUtil.convertMsToUs(SystemClock.elapsedRealtime());BatteryInfo batteryInfo;Estimate estimate = getEnhancedEstimate();// couldn't get estimate from cache or provider, use fallbackif (estimate == null) {estimate = new Estimate(batteryUsageStats.getBatteryTimeRemainingMs(),false /* isBasedOnUsage */,EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);}BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime);batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast,batteryUsageStats, estimate, elapsedRealtimeUs, false /* shortString */);BatteryUtils.logRuntime(tag, "BatteryInfoLoader.loadInBackground", startTime);try {batteryUsageStats.close();} catch (Exception e) {Log.e(TAG, "BatteryUsageStats.close() failed", e);}return batteryInfo;}
frameworks/base/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
    private BatteryUsageStats getCurrentBatteryUsageStats(BatteryUsageStatsQuery query,long currentTimeMs) {final long realtimeUs = elapsedRealtime() * 1000;final long uptimeUs = uptimeMillis() * 1000;final boolean includePowerModels = (query.getFlags()& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;final boolean includeProcessStateData = ((query.getFlags()& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0)&& mStats.isProcessStateDataAvailable();final boolean includeVirtualUids =  ((query.getFlags()& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(mStats.getCustomEnergyConsumerNames(), includePowerModels,includeProcessStateData);// TODO(b/188068523): use a monotonic clock to ensure resilience of order and duration// of stats sessions to wall-clock adjustmentsbatteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());batteryUsageStatsBuilder.setStatsEndTimestamp(currentTimeMs);SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();for (int i = uidStats.size() - 1; i >= 0; i--) {final BatteryStats.Uid uid = uidStats.valueAt(i);if (!includeVirtualUids && uid.getUid() == Process.SDK_SANDBOX_VIRTUAL_UID) {continue;}batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(uid).setTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND,getProcessBackgroundTimeMs(uid, realtimeUs)).setTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND,getProcessForegroundTimeMs(uid, realtimeUs));}final int[] powerComponents = query.getPowerComponents();final List<PowerCalculator> powerCalculators = getPowerCalculators();for (int i = 0, count = powerCalculators.size(); i < count; i++) {PowerCalculator powerCalculator = powerCalculators.get(i);if (powerComponents != null) {boolean include = false;for (int j = 0; j < powerComponents.length; j++) {if (powerCalculator.isPowerComponentSupported(powerComponents[j])) {include = true;break;}}if (!include) {continue;}}powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,query);}if ((query.getFlags()& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY) != 0) {if (!(mStats instanceof BatteryStatsImpl)) {throw new UnsupportedOperationException("History cannot be included for " + getClass().getName());}BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;// Make a copy of battery history to avoid concurrent modification.Parcel historyBuffer = Parcel.obtain();historyBuffer.appendFrom(batteryStatsImpl.mHistoryBuffer, 0,batteryStatsImpl.mHistoryBuffer.dataSize());final File systemDir =batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();final BatteryStatsHistory batteryStatsHistory =new BatteryStatsHistory(batteryStatsImpl, systemDir, historyBuffer);batteryUsageStatsBuilder.setBatteryHistory(batteryStatsHistory);}BatteryUsageStats stats = batteryUsageStatsBuilder.build();if (includeProcessStateData) {verify(stats);}return stats;}// STOPSHIP(b/229906525): remove verification before shippingprivate static boolean sErrorReported;private void verify(BatteryUsageStats stats) {if (sErrorReported) {return;}final double precision = 2.0;   // Allow rounding errors up to 2 mAhfinal int[] components ={BatteryConsumer.POWER_COMPONENT_CPU,BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,BatteryConsumer.POWER_COMPONENT_WIFI,BatteryConsumer.POWER_COMPONENT_BLUETOOTH};final int[] states ={BatteryConsumer.PROCESS_STATE_FOREGROUND,BatteryConsumer.PROCESS_STATE_BACKGROUND,BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE,BatteryConsumer.PROCESS_STATE_CACHED};for (UidBatteryConsumer ubc : stats.getUidBatteryConsumers()) {for (int component : components) {double consumedPower = ubc.getConsumedPower(ubc.getKey(component));double sumStates = 0;for (int state : states) {sumStates += ubc.getConsumedPower(ubc.getKey(component, state));}if (sumStates > consumedPower + precision) {String error = "Sum of states exceeds total. UID = " + ubc.getUid() + " "+ BatteryConsumer.powerComponentIdToString(component)+ " total = " + consumedPower + " states = " + sumStates;if (!sErrorReported) {Slog.wtf(TAG, error);sErrorReported = true;} else {Slog.e(TAG, error);}return;}}}}
frameworks/base/core/java/com/android/internal/os/BatteryChargeCalculator.java
    @Overridepublic void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {builder.setDischargePercentage(batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED));int batteryCapacityMah = batteryStats.getLearnedBatteryCapacity() / 1000;if (batteryCapacityMah <= 0) {batteryCapacityMah = batteryStats.getMinLearnedBatteryCapacity() / 1000;if (batteryCapacityMah <= 0) {batteryCapacityMah = batteryStats.getEstimatedBatteryCapacity();}}builder.setBatteryCapacity(batteryCapacityMah);final double dischargedPowerLowerBoundMah =batteryStats.getLowDischargeAmountSinceCharge() * batteryCapacityMah / 100.0;final double dischargedPowerUpperBoundMah =batteryStats.getHighDischargeAmountSinceCharge() * batteryCapacityMah / 100.0;builder.setDischargePercentage(batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)).setDischargedPowerRange(dischargedPowerLowerBoundMah,dischargedPowerUpperBoundMah).setDischargeDurationMs(batteryStats.getBatteryRealtime(rawRealtimeUs) / 1000);final long batteryTimeRemainingMs = batteryStats.computeBatteryTimeRemaining(rawRealtimeUs);if (batteryTimeRemainingMs != -1) {builder.setBatteryTimeRemainingMs(batteryTimeRemainingMs / 1000);}final long chargeTimeRemainingMs = batteryStats.computeChargeTimeRemaining(rawRealtimeUs);if (chargeTimeRemainingMs != -1) {builder.setChargeTimeRemainingMs(chargeTimeRemainingMs / 1000);}long dischargeMah = batteryStats.getUahDischarge(BatteryStats.STATS_SINCE_CHARGED) / 1000;if (dischargeMah == 0) {dischargeMah = (long) ((dischargedPowerLowerBoundMah + dischargedPowerUpperBoundMah) / 2+ 0.5);}builder.getAggregateBatteryConsumerBuilder(BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE).setConsumedPower(dischargeMah);}
2.1.2 BatteryStatsImpl计算
mBatteryTimeToFullSeconds这个是底层支持计算,由底层health上报。- 计算逻辑
final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);:
- 电池状态信息变化调用**
setBatteryStateLocked**,这里mChargeStepTracker会init()初始化或level增大变化记录计算addLevelSteps
mChargeStepTracker.mNumStepDurations < 1充满一格电不会显示,至少连续充满两格电
mChargeStepTracker.computeTimePerLevel()平均addLevelSteps记录充电每个格电的总时间
(msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;连续充电的平均得到的每格电充电时间 * 需要充电level
frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
    @Overridepublic long computeChargeTimeRemaining(long curTime) {if (mOnBattery) {// Not yet working.return -1;}if (mBatteryTimeToFullSeconds >= 0) {return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us}// Else use algorithmic approachif (mChargeStepTracker.mNumStepDurations < 1) {return -1;}long msPerLevel = mChargeStepTracker.computeTimePerLevel();if (msPerLevel <= 0) {return -1;}return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;}
frameworks/base/core/java/android/os/BatteryStats.java
    public static final class LevelStepTracker {public long mLastStepTime = -1;public int mNumStepDurations;public final long[] mStepDurations;public LevelStepTracker(int maxLevelSteps) {mStepDurations = new long[maxLevelSteps];}public LevelStepTracker(int numSteps, long[] steps) {mNumStepDurations = numSteps;mStepDurations = new long[numSteps];System.arraycopy(steps, 0, mStepDurations, 0, numSteps);}// ... ...public void init() {mLastStepTime = -1;mNumStepDurations = 0;}// ... ...public long computeTimePerLevel() {final long[] steps = mStepDurations;final int numSteps = mNumStepDurations;// For now we'll do a simple average across all steps.if (numSteps <= 0) {return -1;}long total = 0;for (int i=0; i<numSteps; i++) {total += steps[i] & STEP_LEVEL_TIME_MASK;}return total / numSteps;}// ... ...public void addLevelSteps(int numStepLevels, long modeBits, long elapsedRealtime) {int stepCount = mNumStepDurations;final long lastStepTime = mLastStepTime;if (lastStepTime >= 0 && numStepLevels > 0) {final long[] steps = mStepDurations;long duration = elapsedRealtime - lastStepTime;for (int i=0; i<numStepLevels; i++) {System.arraycopy(steps, 0, steps, 1, steps.length-1);long thisDuration = duration / (numStepLevels-i);duration -= thisDuration;if (thisDuration > STEP_LEVEL_TIME_MASK) {thisDuration = STEP_LEVEL_TIME_MASK;}steps[0] = thisDuration | modeBits;}stepCount += numStepLevels;if (stepCount > steps.length) {stepCount = steps.length;}}mNumStepDurations = stepCount;mLastStepTime = elapsedRealtime;}// ... ...}
2.2 电池剩余使用时间
2.2.1 Estimate获取
updateBatteryInfoDischarging获取Estimate中estimateMillis,由2.1.1BatteryUsageStats获取中查看实际获取batteryUsageStats.getBatteryTimeRemainingMs()
BatteryUsageStats中mBatteryTimeRemainingMs查看上面BatteryChargeCalculator.java#calculate最终调用到batteryStats.computeBatteryTimeRemaining(rawRealtimeUs)计算
Estimate.kt如果缓存的估计值可用,则返回该估计值。如果估计不可用或超过2分钟,将返回null。相关属性Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME、Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS、Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE、Settings.Global.AVERAGE_TIME_TO_DISCHARGE
frameworks/base/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
 packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java
    Estimate getEnhancedEstimate() {Estimate estimate = null;// Get enhanced prediction if availableif (Duration.between(Estimate.getLastCacheUpdateTime(mContext), Instant.now()).compareTo(Duration.ofSeconds(10)) < 0) {estimate = Estimate.getCachedEstimateIfAvailable(mContext);} else if (mPowerUsageFeatureProvider != null &&mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) {estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext);if (estimate != null) {Estimate.storeCachedEstimate(mContext, estimate);}}return estimate;}
2.2.2 BatteryStatsImpl计算
- 计算逻辑
final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);:
- 电池状态信息变化调用**
setBatteryStateLocked**,这里mDischargeStepTracker会init()初始化或level减小变化记录计算addLevelSteps
mDischargeStepTracker.mNumStepDurations < 1耗电一格电不会显示,至少连续耗电两格电
mChargeStepTracker.computeTimePerLevel()平均addLevelSteps记录耗电每个格电的总时间
(msPerLevel * mCurrentBatteryLevel) * 1000连续耗电的平均得到的每格电充电时间 * 当前电量level
frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
    public long computeBatteryTimeRemaining(long curTime) {if (!mOnBattery) {return -1;}if (mDischargeStepTracker.mNumStepDurations < 1) {return -1;}long msPerLevel = mDischargeStepTracker.computeTimePerLevel();if (msPerLevel <= 0) {return -1;}return (msPerLevel * mCurrentBatteryLevel) * 1000;}
3、电池信息来源
mHealthServiceWrapper = HealthServiceWrapper.create(this::update);注册监听IHealthInfoCallback.hal,回调执行update > processValuesLocked
android.hardware.health@2.0-service中 轮询更新Health::update(),其中battery_monitor_->logValues()输出日志healthd : battery l=
BatteryService.java#processValuesLocked通过BatteryStatsService.java最终通知到BatteryStatsImpl.java#setBatteryStateLocked;这里输出Event日志battery_level、battery_status、battery_discharge、BatteryService
frameworks/base/services/core/java/com/android/server/BatteryService.java
    private void registerHealthCallback() {traceBegin("HealthInitWrapper");// IHealth is lazily retrieved.try {mHealthServiceWrapper = HealthServiceWrapper.create(this::update);} catch (RemoteException ex) {Slog.e(TAG, "health: cannot register callback. (RemoteException)");throw ex.rethrowFromSystemServer();} catch (NoSuchElementException ex) {Slog.e(TAG, "health: cannot register callback. (no supported health HAL service)");throw ex;} finally {traceEnd();}traceBegin("HealthInitWaitUpdate");// init register for new service notifications, and IServiceManager should return the// existing service in a near future. Wait for this.update() to instantiate// the initial mHealthInfo.long beforeWait = SystemClock.uptimeMillis();synchronized (mLock) {while (mHealthInfo == null) {Slog.i(TAG, "health: Waited " + (SystemClock.uptimeMillis() - beforeWait) +"ms for callbacks. Waiting another " + HEALTH_HAL_WAIT_MS + " ms...");try {mLock.wait(HEALTH_HAL_WAIT_MS);} catch (InterruptedException ex) {Slog.i(TAG, "health: InterruptedException when waiting for update. "+ " Continuing...");}}}Slog.i(TAG, "health: Waited " + (SystemClock.uptimeMillis() - beforeWait)+ "ms and received the update.");traceEnd();}private void update(android.hardware.health.HealthInfo info) {traceBegin("HealthInfoUpdate");Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter", info.batteryChargeCounterUah);Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent", info.batteryCurrentMicroamps);Trace.traceCounter(Trace.TRACE_TAG_POWER, "PlugType", plugType(info));Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryStatus", info.batteryStatus);synchronized (mLock) {if (!mUpdatesStopped) {mHealthInfo = info;// Process the new values.processValuesLocked(false);mLock.notifyAll(); // for any waiters on new info} else {copyV1Battery(mLastHealthInfo, info);}}traceEnd();}private void processValuesLocked(boolean force) {boolean logOutlier = false;long dischargeDuration = 0;mBatteryLevelCritical =mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN&& mHealthInfo.batteryLevel <= mCriticalBatteryLevel;mPlugType = plugType(mHealthInfo);if (DEBUG) {Slog.d(TAG, "Processing new values: "+ "info=" + mHealthInfo+ ", mBatteryLevelCritical=" + mBatteryLevelCritical+ ", mPlugType=" + mPlugType);}// Let the battery stats keep track of the current level.try {mBatteryStats.setBatteryState(mHealthInfo.batteryStatus,mHealthInfo.batteryHealth,mPlugType,mHealthInfo.batteryLevel,mHealthInfo.batteryTemperatureTenthsCelsius,mHealthInfo.batteryVoltageMillivolts,mHealthInfo.batteryChargeCounterUah,mHealthInfo.batteryFullChargeUah,mHealthInfo.batteryChargeTimeToFullNowSeconds);} catch (RemoteException e) {// Should never happen.}shutdownIfNoPowerLocked();shutdownIfOverTempLocked();if (force|| (mHealthInfo.batteryStatus != mLastBatteryStatus|| mHealthInfo.batteryHealth != mLastBatteryHealth|| mHealthInfo.batteryPresent != mLastBatteryPresent|| mHealthInfo.batteryLevel != mLastBatteryLevel|| mPlugType != mLastPlugType|| mHealthInfo.batteryVoltageMillivolts != mLastBatteryVoltage|| mHealthInfo.batteryTemperatureTenthsCelsius != mLastBatteryTemperature|| mHealthInfo.maxChargingCurrentMicroamps != mLastMaxChargingCurrent|| mHealthInfo.maxChargingVoltageMicrovolts != mLastMaxChargingVoltage|| mHealthInfo.batteryChargeCounterUah != mLastChargeCounter|| mInvalidCharger != mLastInvalidCharger)) {if (mPlugType != mLastPlugType) {if (mLastPlugType == BATTERY_PLUGGED_NONE) {// discharging -> chargingmChargeStartLevel = mHealthInfo.batteryLevel;mChargeStartTime = SystemClock.elapsedRealtime();final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);builder.setType(MetricsEvent.TYPE_ACTION);builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mPlugType);builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,mHealthInfo.batteryLevel);mMetricsLogger.write(builder);// 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 != mHealthInfo.batteryLevel) {dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;logOutlier = true;EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,mDischargeStartLevel, mHealthInfo.batteryLevel);// make sure we see a discharge event before logging againmDischargeStartTime = 0;}} else if (mPlugType == BATTERY_PLUGGED_NONE) {// charging -> discharging or we just powered upmDischargeStartTime = SystemClock.elapsedRealtime();mDischargeStartLevel = mHealthInfo.batteryLevel;long chargeDuration = SystemClock.elapsedRealtime() - mChargeStartTime;if (mChargeStartTime != 0 && chargeDuration != 0) {final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);builder.setType(MetricsEvent.TYPE_DISMISS);builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mLastPlugType);builder.addTaggedData(MetricsEvent.FIELD_CHARGING_DURATION_MILLIS,chargeDuration);builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,mChargeStartLevel);builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_END,mHealthInfo.batteryLevel);mMetricsLogger.write(builder);}mChargeStartTime = 0;}}if (mHealthInfo.batteryStatus != mLastBatteryStatus ||mHealthInfo.batteryHealth != mLastBatteryHealth ||mHealthInfo.batteryPresent != mLastBatteryPresent ||mPlugType != mLastPlugType) {EventLog.writeEvent(EventLogTags.BATTERY_STATUS,mHealthInfo.batteryStatus, mHealthInfo.batteryHealth, mHealthInfo.batteryPresent ? 1 : 0,mPlugType, mHealthInfo.batteryTechnology);}if (mHealthInfo.batteryLevel != mLastBatteryLevel) {// Don't do this just from voltage or temperature changes, that is// too noisy.EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,mHealthInfo.batteryLevel,mHealthInfo.batteryVoltageMillivolts,mHealthInfo.batteryTemperatureTenthsCelsius);}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&& mHealthInfo.batteryStatus !=BatteryManager.BATTERY_STATUS_UNKNOWN&& mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {mBatteryLevelLow = true;}} else {// Should we now switch out of low battery mode?if (mPlugType != BATTERY_PLUGGED_NONE) {mBatteryLevelLow = false;} else if (mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel)  {mBatteryLevelLow = false;} else if (force && mHealthInfo.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;}}mSequence++;// 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) {final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);mHandler.post(new Runnable() {@Overridepublic void run() {mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);}});}else if (mPlugType == 0 && mLastPlugType != 0) {final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);mHandler.post(new Runnable() {@Overridepublic void run() {mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);}});}if (shouldSendBatteryLowLocked()) {mSentLowBatteryBroadcast = true;final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);mHandler.post(new Runnable() {@Overridepublic void run() {mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);}});} else if (mSentLowBatteryBroadcast &&mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {mSentLowBatteryBroadcast = false;final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);mHandler.post(new Runnable() {@Overridepublic void run() {mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);}});}// We are doing this after sending the above broadcasts, so anything processing// them will get the new sequence number at that point.  (See for example how testing// of JobScheduler's BatteryController works.)sendBatteryChangedIntentLocked();if (mLastBatteryLevel != mHealthInfo.batteryLevel || mLastPlugType != mPlugType) {sendBatteryLevelChangedIntentLocked();}// Update the battery LEDmLed.updateLightsLocked();// This needs to be done after sendIntent() so that we get the lastest battery stats.if (logOutlier && dischargeDuration != 0) {logOutlierLocked(dischargeDuration);}mLastBatteryStatus = mHealthInfo.batteryStatus;mLastBatteryHealth = mHealthInfo.batteryHealth;mLastBatteryPresent = mHealthInfo.batteryPresent;mLastBatteryLevel = mHealthInfo.batteryLevel;mLastPlugType = mPlugType;mLastBatteryVoltage = mHealthInfo.batteryVoltageMillivolts;mLastBatteryTemperature = mHealthInfo.batteryTemperatureTenthsCelsius;mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrentMicroamps;mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltageMicrovolts;mLastChargeCounter = mHealthInfo.batteryChargeCounterUah;mLastBatteryLevelCritical = mBatteryLevelCritical;mLastInvalidCharger = mInvalidCharger;}}
hardware/interfaces/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
void healthd_mode_service_2_0_battery_update(struct android::BatteryProperties* prop) {HealthInfo info;convertToHealthInfo(prop, info.legacy);Health::getImplementation()->notifyListeners(&info);
}static struct healthd_mode_ops healthd_mode_service_2_0_ops = {.init = healthd_mode_service_2_0_init,.preparetowait = healthd_mode_service_2_0_preparetowait,.heartbeat = healthd_mode_service_2_0_heartbeat,.battery_update = healthd_mode_service_2_0_battery_update,
};int health_service_main(const char* instance) {gInstanceName = instance;if (gInstanceName.empty()) {gInstanceName = "default";}healthd_mode_ops = &healthd_mode_service_2_0_ops;LOG(INFO) << LOG_TAG << gInstanceName << ": Hal starting main loop...";return healthd_main();
}
hardware/interfaces/health/2.0/default/healthd_common_adapter.cpp
// Adapter of HealthLoop to use legacy healthd_mode_ops.
class HealthLoopAdapter : public HealthLoop {public:// Expose internal functions, assuming clients calls them in the same thread// where StartLoop is called.int RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) {return HealthLoop::RegisterEvent(fd, func, wakeup);}void AdjustWakealarmPeriods(bool charger_online) {return HealthLoop::AdjustWakealarmPeriods(charger_online);}protected:void Init(healthd_config* config) override { healthd_mode_ops->init(config); }void Heartbeat() override { healthd_mode_ops->heartbeat(); }int PrepareToWait() override { return healthd_mode_ops->preparetowait(); }void ScheduleBatteryUpdate() override { Health::getImplementation()->update(); }
};
hardware/interfaces/health/utils/libhealthloop/HealthLoop.cpp
void HealthLoop::PeriodicChores() {ScheduleBatteryUpdate();
}void HealthLoop::MainLoop(void) {int nevents = 0;while (1) {reject_event_register_ = true;size_t eventct = event_handlers_.size();struct epoll_event events[eventct];int timeout = awake_poll_interval_;int mode_timeout;/* Don't wait for first timer timeout to run periodic chores */if (!nevents) PeriodicChores();Heartbeat();mode_timeout = PrepareToWait();if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout;nevents = epoll_wait(epollfd_, events, eventct, timeout);if (nevents == -1) {if (errno == EINTR) continue;KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");break;}for (int n = 0; n < nevents; ++n) {if (events[n].data.ptr) {auto* event_handler = reinterpret_cast<EventHandler*>(events[n].data.ptr);event_handler->func(event_handler->object, events[n].events);}}}return;
}
hardware/interfaces/health/2.0/default/Health.cpp
Return<Result> Health::update() {if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {LOG(WARNING) << "health@2.0: update: not initialized. "<< "update() should not be called in charger";return Result::UNKNOWN;}// Retrieve all information and call healthd_mode_ops->battery_update, which calls// notifyListeners.battery_monitor_->updateValues();const HealthInfo_1_0& health_info = battery_monitor_->getHealthInfo_1_0();struct BatteryProperties props;convertFromHealthInfo(health_info, &props);bool log = (healthd_board_battery_update(&props) == 0);if (log) {battery_monitor_->logValues();}healthd_mode_ops->battery_update(&props);bool chargerOnline = battery_monitor_->isChargerOnline();// adjust uevent / wakealarm periodshealthd_battery_update_internal(chargerOnline);return Result::SUCCESS;
}void Health::notifyListeners(HealthInfo* healthInfo) {std::vector<StorageInfo> info;get_storage_info(info);std::vector<DiskStats> stats;get_disk_stats(stats);int32_t currentAvg = 0;struct BatteryProperty prop;status_t ret = battery_monitor_->getProperty(BATTERY_PROP_CURRENT_AVG, &prop);if (ret == OK) {currentAvg = static_cast<int32_t>(prop.valueInt64);}healthInfo->batteryCurrentAverage = currentAvg;healthInfo->diskStats = stats;healthInfo->storageInfos = info;std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);for (auto it = callbacks_.begin(); it != callbacks_.end();) {auto ret = (*it)->healthInfoChanged(*healthInfo);if (!ret.isOk() && ret.isDeadObject()) {it = callbacks_.erase(it);} else {++it;}}
}
4、命令模拟
frameworks/base/services/core/java/com/android/server/BatteryService.java
C:\Users\Administrator\Desktop>adb shell cmd battery
Battery service (battery) commands:helpPrint this help text.get [-f] [ac|usb|wireless|status|level|temp|present|counter|invalid]set [-f] [ac|usb|wireless|status|level|temp|present|counter|invalid] <value>Force a battery property value, freezing battery state.-f: force a battery change broadcast be sent, prints new sequence.unplug [-f]Force battery unplugged, freezing battery state.-f: force a battery change broadcast be sent, prints new sequence.reset [-f]Unfreeze battery state, returning to current hardware values.-f: force a battery change broadcast be sent, prints new sequence.suspend_inputSuspend charging even if plugged in.
* 日志
- Event日志
# ---------------------------
# BatteryService.java
# ---------------------------
2722 battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
2723 battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
# This is logged when battery goes from discharging to charging.
# It lets us count the total amount of time between charges and the discharge level
2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
12-23 05:47:45.420   602   764 I battery_status: [2,2,1,1,Li-ion]
12-23 13:13:43.762     0     0 W healthd : battery l=57 v=5000 t=25.0 h=2 st=2 c=900000 fc=3000000 cc=10 chg=a
12-23 13:13:51.756   602   623 I battery_level: [58,5000,250]
12-23 13:13:52.156   994  2461 D BatteryInfoLoader: BatteryInfoLoader post query: 5ms
12-23 13:13:52.168   994  2461 D BatteryInfo: time for getBatteryInfo: 1ms
12-23 13:13:52.170   994  2461 D BatteryInfoLoader: BatteryInfoLoader.loadInBackground: 19ms
12-23 13:13:52.300   994  2131 D BatteryTipLoader: BatteryInfoLoader post query: 6ms
12-23 13:13:52.308   994  2131 D BatteryInfo: time for getBatteryInfo: 1ms
12-23 13:13:52.308   994  2131 D BatteryTipLoader: BatteryInfoLoader.loadInBackground: 15ms
12-23 13:13:57.300   602   623 I battery_level: [59,5000,250]
12-23 13:13:57.706   994  2135 D BatteryTipLoader: BatteryInfoLoader post query: 14ms
12-23 13:13:57.713   994  2135 D BatteryInfo: time for getBatteryInfo: 7ms
12-23 13:13:57.714   994  2135 D BatteryTipLoader: BatteryInfoLoader.loadInBackground: 21ms
12-23 13:13:57.789   994  2461 D BatteryInfoLoader: BatteryInfoLoader post query: 4ms
12-23 13:13:57.792   994  2461 D BatteryInfo: time for getBatteryInfo: 1ms
12-23 13:13:57.793   994  2461 D BatteryInfoLoader: BatteryInfoLoader.loadInBackground: 8ms
相关文章:
 
Settings中电池选项-Android13
Settings中电池选项-Android13 1、设置中界面2、电池计算2.1 充电时间计算2.1.1 BatteryUsageStats获取2.1.2 BatteryStatsImpl计算 2.2 电池剩余使用时间2.2.1 Estimate获取2.2.2 BatteryStatsImpl计算 3、电池信息来源4、命令模拟* 日志 [电池]Android 9.0 电池未充电与充电字…...
解密 Java ForEach 提前终止问题
目录 前言:场景复现分析与解决方案解决方案详解总结 前言: 你是否曾在使用 Java 8 的 forEach 迭代集合时遇到过提前终止循环的问题?在这篇博客中,我们将深入探讨这一问题,并提供多种解决方案。通过场景复现、分析源码…...
 
7_js_dom编程入门1
Objective(本课目标) 掌握获取页面元素的常用方法 掌握事件触发案例 能够区分innerText和innerHTML的区别 综合案例训练 1 DOM 介绍 1.1 什么是DOM 文档对象模型(Document Object Model,简称DOM),是 …...
 
使用 Elasticsearch 检测抄袭 (一)
作者:Priscilla Parodi 抄袭可以是直接的,涉及复制部分或全部内容,也可以是释义的,即通过更改一些单词或短语来重新表述作者的作品。 灵感和释义之间是有区别的。 即使你得出类似的结论,也可以阅读内容,获得…...
 
STM32 cubeMX 直流电机控制风扇转动
本文使用的是 HAL 库。 文章目录 前言一、直流电机介绍二、直流电机原理图三、直流电机控制方法四、STM32CubeMX 配置直流电机五、代码编写总结 前言 实验开发板:STM32F051K8。所需软件:keil5 , cubeMX 。实验目的:了解 直流电机…...
 
我在 VSCode 插件里接入了 ChatGPT,解决了Bug无法定位的难题
作为一名软件开发者,我时常面临着代码中Bug的定位和解决问题。这个过程往往既费时又充满挑战。然而,最近我在我的VSCode插件中接入了ChatGPT,这个决定彻底改变了我处理Bug的方式。 Bug:开发者的噩梦 在开发过程中,遇…...
学Java的第四天
一、switch语句 switch (表达式) { case 1: 语句体1; break; case 2: 语句体2; break; ... default: 语句体n1; break; } 首先计算表达式的值,然后和case 比较,有对应的值就执行对应的语句,遇到 break 就结束。 最后如果所有的cas…...
 
[内功修炼]函数栈帧的创建与销毁
文章目录 1:什么是函数栈帧2:理解函数栈帧能解决什么问题呢3:函数栈帧的创建与销毁的解析3.1:什么是栈3.2:认识相关寄存器与汇编指令相关寄存器相关汇编指令 3.3 解析函数栈帧的创建和销毁3.3.1 预备知识3.3.2 详细解析一:调用main函数,为main函数开辟函数栈帧First:push前push…...
 
【深度学习-目标检测】03 - Faster R-CNN 论文学习与总结
论文地址:Faster R-CNN: Towards Real-Time ObjectDetection with Region Proposal Networks 论文学习 1. 摘要与引言 研究背景与挑战:当前最先进的目标检测网络依赖于 区域提议(Region Proposals)来假设目标的位置,…...
oracle11体系结构二-存储结构
数据区: 数据区(数据扩展区)由一组连续的oracle数据块所构成的存储结构,一个或多个数据块组成一个数据区,一个或多个数据区组成一个段。当段中所有空间被使用完后,oracle系统将自动为该段分配一个新的数据…...
 
如何通过内网穿透实现远程访问本地Linux SVN服务
文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…...
 
网页乱码问题(edge浏览器)
网页乱码问题(edge) 文章目录 网页乱码问题(edge)前言一、网页乱码问题1.是什么:(描述)2.解决方法:(针对edge浏览器)(1)下载charset插…...
 
泛微OA xmlrpcServlet接口任意文件读取漏洞(CNVD-2022-43245)
CNVD-2022-43245 泛微e-cology XmlRpcServlet接口处存在任意文件读取漏洞,攻击者可利用漏洞获取敏感信息。 1.漏洞级别 中危 2.影响范围 e-office < 9.5 202201133.漏洞搜索 fofa 搜索 app"泛微-OA(e-cology)"4.漏洞复现 …...
 
MATLAB ga函数的使用方法
一、ga句法结构 x ga(fitnessfcn,nvars) x ga(fitnessfcn,nvars,A,b) x ga(fitnessfcn,nvars,A,b,Aeq,beq) x ga(fitnessfcn,nvars,A,b,Aeq,beg,IB,UB) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon,options) x …...
 
基于STM32和MQ-2传感器的无线烟雾检测系统设计
随着科技的不断发展,人们对生活安全的要求也越来越高。其中,烟雾检测系统在预防火灾方面起着至关重要的作用。本文将介绍一种基于STM32和MQ-2传感器的无线烟雾检测系统设计,旨在实时检测环境中的烟雾,并及时发出警报,以…...
 
华为vrrp+mstp+ospf+dhcp+dhcp relay配置案例
1、左边是vlan 10主桥,右边是vlan 20的主桥,并且互为备桥 2、 vlan 10 vrrp网关默认用左边,vlan 20的vrrp 网关默认用右边,对应mstp生成树 3、两边都track检测,不通就把vrrp减掉60,这样就会自动切另一边了 …...
5-Docker实例-tomcat application
1.安装如下树形结构创建目录及文件,内容如下: 目录结构: [root@centos79 ~]# tree demo demo ├── index.html └── WEB-INF└── web.xml1 directory, 2 files [root@centos79 ~]# index.html文件内容 [root@centos79 demo]# cat index.html <h1>hello dock…...
 
Pikachu靶场 “Http Header”SQL注入
1. 先在 pikachu 打开 Http Header 注入模块,点击提示 查看登录 账号 和 密码,登陆后去 Burp 中找到登陆的 GET请求 2. 设置payload1 :在 User-Agent最后 输入 查看 数据库名 or updatexml(1,concat(0x7e,database()),0) or 查看 用户名…...
 
OpenEuler安装内网穿透工具实现ssh连接openEuler系统
文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 本文主要介绍在openEuler中安装Cpolar内网穿透工具实现远程也可以ssh 连接openEuler系统使用. 欧拉操作系统(openEuler, 简称“欧拉”…...
【效率工具】利用python进行本地知识库(PDF和WORK文件内容)的批量模糊搜索
目录 前言 一、为什么要进行本地文档的批量搜索? 二、如何去做呢?...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
 
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
 
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
 
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
 
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
 
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
 
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
 
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
 
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
