Re: CfC: Battery Last Call

On 21.11.2011, at 13.45, ext Mounir Lamouri wrote:

> My suggestion wasn't to add a feature detection method but a way to know if the device has a battery. Knowing if the Battery API is enabled in the UA should be as simple as ("battery" in navigator) but knowing if the device has a real battery is harder. As I said, our current API allows that in an unintuitive way: (battery.chargingTime === Infinity && battery.level === 1.0) [1][2].
> 
> What I propose is to add an attribute (I don't care about the naming) that would let authors to know more explicitly and simply if the device has a battery.
> In one hand, that would prevent dirty hack like above when the Web App really needs to know if there is a battery. In the other hand, some authors might use it even when not needed like:
> if (battery.hasBattery && battery.level < 0.5) {
>  // do battery-saving stuff
> } else {
>  // do CPU-expensive stuff
> }
> The condition could have been |if (battery.level < 0.5)|.

I think we should try to make the common use cases simple, and also try to make the API self-documenting. I feel the latter form would be preferred.

I also very much like the "when in doubt leave it out" rule of API design: we can add things later, but can't take them away (after shipping, that is).

> However, I do not think there are a lot of use cases where knowing if the device has a battery is useful.

Agreed. We shouldn't design the API for those use cases, but we could enable those if that's possible without increasing the API surface.

> Actually, the only one I see is for a Battery Widget/UI: it shouldn't draw a charging battery if there is actually no battery.

Yes, and this is not a common use case, so we should not add an attribute for this use case only.

> Taking this into account, maybe we could fix the current way to know if there is a battery (see [2]) and add an attribute that will return if there is a battery but hide it behind some kind of security/permission. That way, we could hope authors will not try to read that when they don't need it and apps that really need it will ask for it. Though, it might be worse if authors uselessly read the attribute en masse.

I would prefer to not to go down the route of requiring permissions -- at least not yet. But I like your proposal at [2]. 

> Another solution would be to move this information to another API that would return system informations like if the device has a GPS, a WIFI connectivity, Bluetooth, etc.

This model (decoupling the APIs and their inherent system information) is something that hasn't been used on the web platform -- we tried it, but it did not work out (see System Information API). We should be extra careful and learn from the past if we go down this route again.

> [1] The condition I gave in a previous email was actually not always correct.
> [2] We could probably prevent this by always returning chargingTime = 0 if there is no battery. Actually, that might be a better behavior.

Currently we can deduce the following based on the chargingTime and dischargingTime alone (I think only a battery widget would be interested in all these states, so not a common use case):

if (0 < chargingTime && chargingTime < Infinity) {
  // battery is charging, chargingTime seconds until full
} else if (chargingTime === 0) {
  // battery is full
} else if (chargingTime === Infinity && dischargingTime < Infinity) {
  // battery is discharging, dischargingTime seconds left
} else if (chargingTime === Infinity && dischargingTime === Infinity) {
  // unable to report [chargingTime and dischargingTime]
  // no battery
}

Currently we're unable to differentiate between "no battery" and "unable to report [chargingTime and dischargingTime]" states. And because |level| returns 1.0 for both "no battery" and "unable to report", and |charging| returns false for both the conditions as well, we do not get any better granularity than this.

By returning |chargingTime = 0| also if there is no battery (in addition to "battery full" state) as Mounir suggests, we could test against |charging| to differentiate between "battery is full" and "no battery" states and be able to identify all the states:

if (0 < chargingTime && chargingTime < Infinity) {
  // battery is charging, chargingTime seconds until full
} else if (charging && chargingTime === 0) {
  // battery is full
} else if (!charging && chargingTime === 0) {
  // no battery
} else if (chargingTime === Infinity && dischargingTime < Infinity) {
  // battery is discharging, dischargingTime seconds left
} else if (chargingTime === Infinity && dischargingTime === Infinity) {
  // unable to report [chargingTime and dischargingTime]
}

As said, the above use case is not too common, so the code would be much simpler for typical use cases. For example:

if (dischargingTime < 60 * 10) {
  // 10 minutes battery left
}

if (0 < chargingTime && chargingTime < Infinity) {
  // chargingTime seconds left until fully charged
}

Given this, I agree with Mounir that we should return chargingTime = 0 also if there is no battery. With this change the API is optimized for the common use cases of figuring out the battery's discharging time, level and charging state, but it still enables less common use cases, such as battery widgets.

Please let me know if there's a flaw in my logic above, or if you feel that the proposed change is not right (please include your reasoning). Otherwise, I'll change the spec accordingly before we publish.

-Anssi

Received on Tuesday, 22 November 2011 09:24:19 UTC