VR-25 / acc

Advanced Charging Controller
https://github.com/Magisk-Modules-Repo/acc
GNU General Public License v3.0
1.66k stars 104 forks source link

Simple front-end named `ACC Settings` #110

Open CrazyBoyFeng opened 2 years ago

CrazyBoyFeng commented 2 years ago

As you know, I'm writing a new simple front-end.
Currently I have some questions about handling exit codes.

The exit code 11 means e-current out of range.
The e-current-related commands are these:

And when does the 11 return?

VR-25 commented 2 years ago

You're not supposed to use camelcase there. That's for internal variables only.

-s|--set c|--current [milliamps|-]   Set/print/restore_default max charging current (range: 0-9999 Milliamps)
    e.g.,
      acc -s c (print current limit)
      acc -s c 500 (set)
      acc -s c - (restore default)

-sc [milliamps|-]   Same as above

You get exit code 11 when current is not in the 0-9999 mA range. e.g., /dev/.vr25/acc/acca --set --current -1.

Avoid using regular acc commands. /dev/.vr25/acc/acca is preferred for front-ends. It's faster, lighter, more efficient and runs synchronously. Besides, it's ready right after acc installation/upgrade (i.e., no reboot required to use acc).

I strongly recommend reading notes/tips for front-end developers (I will update this section), default config and terminal commands.

You may also want to read the issues authored by me at AccA's repo.

VR-25 commented 2 years ago

Keep this issue open for anything related to your new project. Questions, suggestions, rants... drop them all here.

CrazyBoyFeng commented 2 years ago

Okay, I'll be doing all front-end development related discussions under this issue.
You can change the title of this issue as you wish.

I now know that exit code 11 is for /dev/.vr25/acc/acca --set --current <n>. So what do you mean by "no camel case"? /dev/.vr25/acc/acca --set prop=value is used to modify the configuration file as I understand.
We have the property maxChargingCurrent, so the command to set this property is /dev/.vr25/acc/acca --set maxChargingCurrent=123.
And /dev/.vr25/acc/acca --set --current 123 is also used to set the maximum charging e-current.
Do they differ in any way?

My current development plan is to imitate the acca's UI. Make a general switch, status display, configuration editing. So I mainly use --set. I will add other functions later if needed.

VR-25 commented 2 years ago

I now know that exit code 11 is for /dev/.vr25/acc/acca --set --current <n>.

As well as for --set mcc=[v] and --set max_charging_current=[v].

So what do you mean by "no camel case"? /dev/.vr25/acc/acca --set prop=value is used to modify the configuration file as I understand.

Camelcase variables are internal. While --set works with some, it's just a coincidence. Thus, I don't recommend using them in the command line. Refer to the bottom of this comment for a complete list of variables and aliases to use with --set.

By the way, you can set multiple props with a single command - that's more efficient (i.e., --set prop1=1 prop2="string 1" ...). You can even run multiple instances of acca --set prop= ... in parallel (acc --set does not support this one). --set prop= resets prop's value to default (which is not necessarily null). Take advantage of this.

We have the property maxChargingCurrent, so the command to set this property is /dev/.vr25/acc/acca --set maxChargingCurrent=123. And /dev/.vr25/acc/acca --set --current 123 is also used to set the maximum charging e-current. Do they differ in any way?

maxChargingCurrent should be replaced with max_charging_current or mcc. --set --current [v] and --set max_charging_current=[v] work the same way. Since you can set multiple properties with a single command, the latter is preferred.

My current development plan is to imitate the acca's UI. Make a general switch, status display, configuration editing. So I mainly use --set. I will add other functions later if needed.

/dev/.vr25/acc/acca --set is really all you need.

What to use with --set (this is in the default configuration section):

cc cooldown_capacity rc resume_capacity pc pause_capacity cft capacity_freeze2

sc shutdown_capacity ct cooldown_temp cch cooldown_charge cp cooldown_pause

mt max_temp mtp max_temp_pause

st shutdown_temp

ccu cooldown_custom cdc cooldown_current

rbsp reset_batt_stats_on_pause rbsu reset_batt_stats_on_unplug

s charging_switch

ab apply_on_boot ap apply_on_plug

mcc max_charging_current mcv max_charging_voltage

l lang rcp run_cmd_on_pause

af amp_factor vf volt_factor

lc loop_cmd pbim prioritize_batt_idle_mode cw current_workaround

CrazyBoyFeng commented 2 years ago

Unofficially supported front-ends must specify the parent installation directory.

Is the intent of this to not conflict with acca? I noticed that acca installs acc in its own application data directory. This way as acca is uninstalled, acc is automatically removed as well. Should I install acc into my application data directory as well?

Does the exit code also apply with sh install-tarball.sh acc?

acca --daemon has no output and exit at 0 when the daemon is running. Is this a bug?

VR-25 commented 2 years ago

Unofficially supported front-ends must specify the parent installation directory.

This is not mandatory. Forget it. I'm updating the documentation.

Is the intent of this to not conflict with acca? I noticed that acca installs acc in its own application data directory. This way as acca is uninstalled, acc is automatically removed as well. Should I install acc into my application data directory as well?

This is optional and I'm improving the default behavior. Even if acc is not installed in acca's data directory, it'll still remove itself on the next boot after acca is uninstalled. This only recognizes acca for now. I'm making it work with all future front-ends.

Does the exit code also apply with sh install-tarball.sh acc?

Yes, 0 (success), 1 (failure), 3 (no busybox) and 4 (no root).

acca --daemon has no output and exit at 0 when the daemon is running. Is this a bug?

acca commands generally do not output anything unless it's really necessary (e.g., acca --set --print). Those rely heavily on exit codes.

Speaking of acca --set --print (or acca -sp)... Your're not supposed to parse the config file directly (that's unsupported). acca --set --print prop will print prop=value. acca --set --print prints all props and respective values. acc --set --print <"REGEX"> also works.

Here's an updated documentation in HTML format. It's still not as comprehensive as I would like it to be, but it has more and better information now - including a table of contents. Revisit the notes/tips for front-end developers section. README.zip

CrazyBoyFeng commented 2 years ago

Some of the output of --info I don't quite understand:

VOLTAGE_MAX_DESIGN=4320000 # static VOLTAGE_MIN_DESIGN=4400000 # static

why min>max?

CAPACITY=50 TEMP=281 SYSTEM_TEMP_LEVEL=0 CURRENT_NOW=0 VOLTAGE_NOW=3.861 POWER_NOW=0 # curr*volt

* what are these?

PRESENT=1 ONLINE=1 CYCLE_COUNT=0 CHARGE_NOW=5071

VR-25 commented 2 years ago

The output of --info comes from the kernel, not acc.

Let the front-end parse only what makes sense to you. Most of these values are either unnecessary (e.g., type: everyone knows that already) or unreliable (e.g., health, speed) anyway. Some kernels provide more information than others.

Here's what you should focus on:

STATUS=Charging # Charging, Not charging (idle mode) or Discharging CAPACITY=50 # Battery level, 0-100 TEMP=281 # Always in ºC 10 CURRENT_NOW=0 # Charging current in Amps VOLTAGE_NOW=3.861 # Charging voltage in Volts POWER_NOW=0 # curr volt in Watts

Note that the power information refers to what is actually supplied to the battery, not what's coming from the adapter. External power is always converted before it reaches the battery.

I'll add this to the doc.

VR-25 commented 2 years ago

The README was updated. I highly recommend reviewing notes/tips for front-end developers.

Also, here's the right way of initializing acc on boot_completed AND main_activity:

on boot_completed receiver and main activity
  if file /dev/.acca/started does NOT exist
    create it
      mkdir -p /dev/.acca
      touch /dev/.acca/started
    if accd is NOT running
      launch it
        /data/adb/vr25/acc/service.sh

Single line shell script: if ! test -f /dev/.acca/started; then mkdir -p /dev/.acca; touch /dev/.acca/started; if ! /dev/.vr25/acc/acca -D 2>/dev/null; then /data/adb/vr25/acc/service.sh; fi; fi

CrazyBoyFeng commented 2 years ago

Why create and detect /dev/path/started_flag file. Wouldn't it be enough to just detect --daemon and run service.sh?

VR-25 commented 2 years ago

No. There are 3 main reasons for this.

  1. ACC's working environment must be initialized - i.e., by updating the stock charging config (for restoring without a reboot) and pre-processing data for greater efficiency. This is done exactly once after boot. If it were done only after installation/upgrade, one would have to reinstall/upgrade acc after every kernel update. That's because kernel updates often change the default power supply drivers settings.

  2. Since acc's core executables are dynamic ([expected to] change regularly), those are linked to /dev/.vr25/acc/ to preserve the API. The links must be recreated once after boot (/dev/ is volatile).

  3. Following 2., accd is a symbolic link to service.sh. If service.sh is executed every time the main activity is launched, accd will be repeatedly restarted for no reason.

Here's a more concise way of handling this:

on boot_completed receiver and main activity
  if acca executable does not exist, initialize acc

The script: [ -f /dev/.vr25/acc/acca ] || /data/adb/vr25/acc/service.sh or test -f /dev/.vr25/acc/acca || /data/adb/vr25/acc/service.sh

I'll update the doc.

CrazyBoyFeng commented 2 years ago

I get it. My previous implementing was:

acca --daemon
# if acca does not exist, $? is 127
if [ "$?" -ne "0" ]
    service.sh
fi

The downside of this is that if the user manually shuts down the daemon, then reopen the app will cause the daemon to start unexpectedly.

I have another question: do I need to run service.sh after updating/reinstalling acc?

VR-25 commented 2 years ago

I have another question: do I need to run service.sh after updating/reinstalling acc?

No. The installer always runs it.

Keep those great questions coming!

VR-25 commented 2 years ago

Note: this "manual" initialization is only strictly required if Magisk is not installed - and only once per boot session. In other words, Magisk already runs service.sh shortly after boot.

CrazyBoyFeng commented 2 years ago

As an app, it is difficult to detect the presence of magisk, so the scheme to detect acca is better than the started_flag file scheme. On a magisk device, the absence of the flag file can make the app mistakenly think that acc is not initialized.

CrazyBoyFeng commented 2 years ago
VR-25 commented 2 years ago
  • Is max_temp_pause redundant? As I understand it, when max_temp is set, acc will loop to detect if temperature is higher than max_temp and then pause charging. Then setting the duration of loops seems to be meaningless. Because no matter how long this cycle is set, acc will not charge until it drops to the max_temp.

max_temp_pause is somewhat redundant, but it helps extend the inactive (sleep) within the max_temp loop. This saves some resources (i.e., accd does not recheck _maxtemp as often).

  • Will setting cooldown_current disable cooldown_charge and cooldown_pause?

No, those work together. While the regular cooldown pauses (for _cooldownpause seconds) and resumes (for _cooldowncharge seconds), cooldown_current lowers the current (for _cooldownpause seconds) instead of pausing charging - and applies the usual/default current limit (for _cooldowncharge seconds).

  • reset_batt_stats_on_pause and reset_batt_stats_on_unplug What does it mean to reset "the battery status"? All timers to zero? What settings does it affect?

Those reset Android battery statistics (stats). That's just the battery usage log under settings > battery.

CrazyBoyFeng commented 2 years ago

Questions about charging_switch:

VR-25 commented 2 years ago
  • When controlling the charging switch by voltage, does it have only one value of 3700?

Not necessarily. The allowed range is 3700-4300 millivolts. However, For the purpose of disabling charging, there's generally no point in using values other than the minimum (3700).

  • When controlling the charging switch by current, is the value arbitrary?

The allowed range is 0-9999 milliamperes However, just like the above, for disabling charging, this approach only makes sense when the current is low enough (e.g., 0-250 mA or so).

  • I noticed that --test can detect if battIdleMode is valid. Is the automatic detection of the charging switch the same as --test? Does this mean that the autodetection of the charging switch also includes the autodetection of battIdleMode? If the answer is yes, then is prioritize_batt_idle_mode only useful when auto-detection is turned off, i.e. --set "charging_switch=[some switch] --"?

--test is for the user only. Internally, acc uses other (yet similar) logic to detect (and set) working switches and idle mode support.

Charging switches that fail to disable charging are automatically unset, unless the trailing string (--) is present. prioritize_batt_idle_mode=true only has effect when charging_switch is not set.

Note: autmode is on when either charging_switch is unset or -- is missing.

CrazyBoyFeng commented 2 years ago

A usable version is out: https://github.com/CrazyBoyFeng/AccSettings/releases Minimum Android version: 4.0 (API level 14) You can also compile and package it yourself with Android Studio or Gradle.

There are still some features planning:

Please let me know if you have any comments or suggestions.

VR-25 commented 2 years ago

I've only been doing light testing lately. So far so good, I really like the simple, yet feature packed design. I'll be conducting more in-depth testing after the next acc release. Just saw a new pre-release. Keep it up!

VR-25 commented 2 years ago

acc v2021.9.19 is up!

CrazyBoyFeng commented 2 years ago

Originally, the purpose of capacity_freeze2 was to stop the system capacity from dropping below 2%, thus preventing the system from shutting down automatically. But after changing to capacity_mask, it seems that the system capacity can drop below 2% (e.g. 1≈1*(100/80)) or even 0%, which means it will still shut down automatically. This seems inconsistent with the purpose of this feature. Am I understanding it right? Is that how capacity_mask works?

Also, did you miss the case when pause_capacity is set in voltage? 1≈50*(100/3700)

VR-25 commented 2 years ago
# capacity_mask (cm) #
# This forces Android to report "capacity = capacity * (100 / pause_capacity)", effectively masking capacity limits.
# It also prevents Android from getting capacity readings below 2% (because some systems shutdown before battery level actually drops to 0%).

Of course, this is only relevant when pause_capacity is in %. It does not make sense otherwise.

If one installs acc on their grandpa's phone, with _capacitymask, they would not get mad at all. It'll look like the battery is charging to 100%, "as it should." This means, if _pausecapacity is 75% and the current battery level is, say 55%, acc will force Android to report 55% * 1.33 = ~73%.

CrazyBoyFeng commented 2 years ago

I seem to understand that the formula capacity = capacity * (100 / pause_capacity) doesn't work when capacity<2, it will still lock at 2% as before.

VR-25 commented 2 years ago

I forgot to mention that besides the formula, there's a filter that won't allow Android to get any readings below 2%.

CrazyBoyFeng commented 2 years ago

I think capacity_freeze2 and capacity_mask would be better as two separate features. This also has some backward compatibility. What if someone wants to prevent shutting down, but doesn't need masking capacity? Or vice versa?

What do you think of this idea?

VR-25 commented 2 years ago

Sure. Separating both features is straightforward - even more so now that acc supports plugins. But I merged capacity_freeze2 with the new mask thing because it was never really used by the masses. I actually implemented it almost exclusively for myself - for a broken phone I wanted to keep running for a while longer. I've never heard of anyone who had the same issue and who would find capacity_freeze2 a game changer. That said, such shutdown issue is rare and happens pretty much only due to a severely damaged battery. Removing features almost nobody uses improves efficiency. Nevertheless, I'm open to bringing the feature back if demand for it increases.

VR-25 commented 2 years ago

Among other changes, the next release will include the following:

capacity_mask (cm)

This forces Android to report "capacity = capacity * (100 / pause_capacity)", effectively masking capacity limits (more like capacity_sync on steroids).

It also prevents Android from getting capacity readings below 2%, since some systems shutdown before battery level actually drops to 0%.


Your front-end is looking great!
So far, it's the most compatible and has the most concise design.
Keep it up!

P.S., capacity_freeze2 worked just like capacity_sync.
However, capacity_sync did not have the `freeze at 2%` logic.
VR-25 commented 2 years ago

Here's some info you might find useful. Nothing new, just a clarification and memory refresher. I updated the documentation.

ACC daemon does not have to be restarted after making changes to the config. It picks up new changes within seconds.

There are a few exceptions:

Profiles

Those are simply different config files. A config path can be supplied as first argument to acca and second to accd executables.

Examples:

Copy the config:

Current config: /dev/.vr25/acc/acca --config cat > /path/to/new/file

Default config: /dev/.vr25/acc/acca /path/to/new/file --version (--version can be replaced with any option + arguments, as seen below.)

Edit the copy:

/dev/.vr25/acc/acca /path/to/new/file --set pause_capacity=75 resume_capacity=70 (if the file does not exist, it is created as a copy of the default config.)

Use the copy:

/dev/.vr25/acc/accd --init /path/to/new/file (the daemon is restarted with the new config.)

Back to the main config:

/dev/.vr25/acc/accd --init

VR-25 commented 2 years ago

https://github.com/VR-25/acc/releases/tag/v2021.9.20

CrazyBoyFeng commented 2 years ago

I'm using --set, which doesn't seem to require a manual restart. The description of --set says it will automatically restart the daemon even after changing charging_switch.

Also, I have not implemented multi-profile support with the current ACC Settings. If you think this feature is important, I will try to implement it.

VR-25 commented 2 years ago

Multi-profiles work well with scheduling. Without that, it's not really needed.

Only acc --set handles the restarts (and re-initializations) as needed. acca --set does not do it, to prevent race conditions. Unlike acc --set, acca --set runs synchronously. The doc was not clear enough about this distinction.

CrazyBoyFeng commented 2 years ago

Got it, using acca --set still requires manual restart. I will add it later.

CrazyBoyFeng commented 2 years ago
VR-25 commented 2 years ago

Is it valid to restart with acca --daemon restart?

Yes. But I believe /dev/.vr25/acc/accd is more concise. It handles start and restart as is (i.e., without any options/arguments).

Is it valid to reinitialize with acca --daemon --init?

No, this is yet to be implemented. Use /dev/.vr25/acc/accd --init.

brightplastik commented 1 year ago

Github at its best, really. You guys together are stronger than the power of nature. I admire you. Your combined work is a marvel.

Iey4iej3 commented 2 months ago

To clarify, the front-end is at https://github.com/CrazyBoyFeng/AccSettings

fillwithjoy1 commented 2 months ago

To clarify, the front-end is at https://github.com/CrazyBoyFeng/AccSettings

thats.... the author's work? great job