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文件内容)的批量模糊搜索
目录 前言 一、为什么要进行本地文档的批量搜索? 二、如何去做呢?...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...