There's no "Skia color profile" per se. When Skia's asked to write a JPEG from a pixel buffer tagged with a color profile (SkColorSpace), we auto-generate an ICC profile programatically from the parameters that describe the color gamut and transfer functions we use to represent those color profiles. That's what the code in this file is up to: https://source.chromium.org/chromium/chromium/src/+/master:t...
So this profile is one of infinite possible profiles that'll have "Google/Skia/..big long MD5.." somewhere in them.
This profile in particular looks like it's probably describing the ProPhoto color space, which is very, very large and uses imaginary colors outside visible light to increase its gamut. While the JPEG itself is always storing values in range in the ProPhoto gamut, when you convert that to another gamut (say, to match the display, or to sRGB) it's very easy to end up with logical color channel values less than zero or greater than one, which do make a kind of sense, but not to code that expects colors are always sRGB bytes.
It's unclear to me what gamut the colors being read in that Java code are in,
and that'd very much affect what the appropriate values for that LUMINOSITY_MATRIX should be. Those are the correct values to get the luminosity for sRGB colors (though I think what's being calculated here is subtly-different gamma-encoded "luma" instead), but they're not likely a sound way to get luminosity if the image is in any different gamut. A typical strategy is to convert any image you load to the display gamut early, since you'll need to do that eventually to display it. And it's more and more common that phone display gamuts are not sRGB, usually something wider now like Display P3.
> out of bounds write in Java
Isn't Java supposed to be a language safe from these kinds of bugs? At the very worst it throws an exception, which should be caught and dealt with accordingly… How can that crash the whole phone?
Yes, from what I have read that's exactly what was happening, it was throwing an IndexOutOfBoundsException. Apparently, nothing was catching that exception, so the whole process was terminated.
> How can that crash the whole phone?
The main problem is that the process which was crashing is the Android equivalent of the window manager or the X server. It recovered from that crash either by restarting the process (which immediately crashed again), or by rebooting the phone (and immediately crashing again).
Apposite moment perhaps to refer to the mind-boggling finding in "Simple Testing Can Prevent Most Critical Failures: An Analysis of Production Failures in Distributed Data-Intensive Systems" (Yuan et al, Usenix 2014 https://www.usenix.org/conference/osdi14/technical-sessions/...):
"almost all (92%) of the catastrophic system failures [in the real-world study] are the result of incorrect handling of non-fatal errors explicitly signaled in software"
It absolutely results in the same kinds of failures.
Perhaps there is no catch at all, so the systemUI process crashes. Since that process is critical, and responsible for things like the status bar, some supervisory process panics, and reboots the phone.
Alternatively perhaps a higher level catch clause does catch this error, but it is at too high a level to be able to recover cleanly by say displaying a black background instead of the wallpaper.
Hard to say without being more familar with the codebase.
I didn't always have this habit, but picked it up when I switched from working on servers to working on safety-critical hardware. It was a lot easier a habit to pick up than I thought it would be, and I've found it makes you write a more robust, well-understood system.
It's quite a responsibility on the human side of software. Handling unexpected errors is a pretty easy thing to miss, for programmers who are inexperienced or have become too comfortable (not paying attention to every detail).
I can't help but think that the language or compiler (or tests, I suppose) could enforce this better, so that it forces the programmer to explicitly handle recovery from failures - at certain layers/thresholds - so that the error doesn't bubble up to the top and bring the whole thing down.
As you pointed out, an error in the UI layer shouldn't have been allowed to trigger a system crash loop. But, that's kind of the nature of bugs like these, they creep in through unexpected logic paths. In which case, the development environment needs to better enforce the (explicit) behavior of all possible paths that an error could take. Well, I'm sure that's constantly improving, as a perennial challenge of reliable software, and there will always be a need for discipline and attentiveness by the humans involved.
Sure, agreed, this isn't a post-hoc "what an obvious bug, they should have just <done everything perfectly from the start>". I was just addressing the dichotomy laid out by the GP comment, which only mentioned top-level generic exception handling instead of case-specific, intelligent exception handling.
Obviously, when one thing goes wrong in a program, frequently that leads to other things going wrong, but IMO thats better than crashing the whole process.
Sure, you might get unexpected output, but for many usecases, unexpected output is better than no output at all.
It's not. Crashing the process (if the error remains unhandled at the top level) is the right answer. When the program raises an exception, you want to either handle it or pass it up, not ignore it. It was raised for a reason. Once an error was raised, if the program ignores it and happily continues all bets are off. This is like reasoning out of false premises: everything goes, which is undesirable. Data is probably corrupted, maybe preconditions are unmet.
For this reason, most automated code checkers consider ignoring exceptions a serious antipattern.
Just a single top level catch block would prevent other code after the error occurred from running, which might still be able to work fine without the results of the faulty code.
I think the post above explains why this isn't the case in mission critical software. I'd argue the lesson from software engineering is that it's not advisable in most situations, not just for nuclear reactors. The error was raised by a reason, after all. I'd say it's the opposite: there are some limited cases where you absolutely know the exception is not relevant, and in those cases you can knowingly swallow the exception.
It was an example of blaming a tool for a hypothetical misuse that is not the only way you can use it.
I'll go an extra mile and say I'm familiar with this construct in Basic, have seen it used, and nobody ever checked any error codes when using it. It's a footgun that's used almost exclusively to shoot at feet.
The trouble is that it's really easy to say "access the 10th position in a 5-element array". It's possible to make a programming language that doesn't allow you to say this, but it either makes it really awkward to do anything with arrays, or simply pushes the error somewhere else -- or both.
Java doesn't claim it's magic. It's objectively safer by this measure. (More specifically, Java claims to be "memory safe" )
It's basically the same thing here, but without some physical keys bound to 'switch to new session'. And maybe you can do that over adb anyway, which is about as (not) normal user friendly.
Which is easy when you have an Either<L, R> construct for your returns or when you have checked Exceptions, which Java devs dislike.
So you get errors like this, because devs are often not aware or misremember all the failure modes of calls they make. Because they're only humans and they're using tools and practices that like to pretend everything that matters is the happy path.
Further, I'd say that IndexOutOfBoundsException can happen pretty much everywhere, so it does not make much sense to make it a checked exception anyway.
Indeed. I don't know of any programming languages in which out-of-bounds array access is an error whose handling is enforced by the type system (checked exception, result, etc). Ditto for numeric overflow and division by zero. I believe even Ada doesn't force error handling of these.
If an implementation of an interface can throw an exception that its interface doesn't declare, that breaks the abstraction. How can you safely use the interface? You either have to catch Exception (which is effectively the same as wrapping every exception in some InterfaceException class), or give up on handling any Exceptions thrown by the interface.
That's just how I phrased it 18 hours ago. The thing I find bad about it is not that exceptions have to be declared in the interface, that's good, it's that every implementations will have to declare them also, even in the case that a particular implementation has no failure mode.
But in general, of course an implementation can't just randomly add checked exceptions, because that would violate the Liskov substitution principle.
Unfortunately, because of the way Java handles checked exceptions, I can't feed the supplier with a lambda or any other method reference that I'm aware of that throws a checked exception and let it be passed up to the original caller directly. So I need to catch my checked exceptions and wrap them in an unchecked exception to catch. Not pretty.
There's probably something I'm missing but the language certainly doesn't go out of its way to help with this sort of thing.
That said, I think the decision to do lambdas the way they did tacitly killed checked exceptions.