And in terms of networking, I argued to Firefox OS that the standard Android/iOS style system-wide link-layer oriented network permissions are insane, and could be done better: https://bug945047.bmoattachments.org/attachment.cgi?id=84072... This is well supported by smilliken's top two permissions statistics posted below, and nitrogen's point: "I find it bothersome that basically any app could potentially portscan your network and sell the map."
Over night Android went from a potential production platform to a straight media consumption platform, as now only system apps could write to removable storage.
Since nobody pointed it out yet: that change was done for security reasons, not due to a political conspiracy. Media access was a big hole in the otherwise fine-grained permission model.
Your camera app used to be able to access your WhatsApp backup folder and your documents. It was just a flat file system. Developers would request the permission even though all they needed was a caching folder or something, but they could read and upload all of your documents, too.
This change, while breaking a bunch of applications until they migrate to the new fine-grained API, was a necessary one.
That was about whatsapp doing a major goof and putting private files in a "public" area (every app already had a private area for file storage) and failing to secure them properly (encryption is hard, apparently).
WhatsApp messed it up particularly bad, but it's not the only example. The point is that there was no private access to the SD card. If you had large files that did not fit on the internal storage, using the shared external storage was the only alternative. Developers abused that and ended up putting all sorts of private data on the SD card.
> The point is that there was no private access to the SD card.
Sure there was! Simply generate a random key, store it in the (small) private storage area, and use it to encrypt whatever you want to write. Instant private area!
It uses ext4 on the mixed mode (which incorporates it as system memory), but it should require ext4 for sd cards as well. They cut off USB mass storage support so they have already crossed that line.
The hard part is the user interface, not the backend. The application needs to invoke a privileged UI where the user can choose which files or directories the application may access.
(many storage media are formatted using FAT, so the media API is probably not implemented using Unix permissions)
I'm talking of allowing apps to mark things (like the WhatsApp data previously mentioned) to only be accessible by itself or some other app(s).
As for FAT, I said in another comment that Google has already imposed MTP on us and Android's adoptable storage uses ext4 anyway, so they could easily require it on all removable storage where application data is stored.
What about using the post-kitkat Storage Access Framework and adopting the user-granted permission to access removable storage? That is, once your user manually grants access to a file or directory (in android 7) using the file/directory picker built into Android, your app can keep that permission for later and use it whenever it wants.
I have some bad experiences with mediastorage (the core of SAF) getting the state of the FS royally confused. Various apps used that path even before SAF, because it is also the backend for the Media Transfer Protocol support.
Thing is that SAF only arrived with 4.4, and didn't properly handle anything more than single file access until 5.0. The the write_media_storage permission was introduced in 3.1. Thats some 5 releases and 2 years of goofing around before they sorted their own mess.
Oh and the external_storage permissions where there initially, but they seem to have edited it since in an effort to clear out some non-Android stuff.
This is why I absolutely won't consider any Android devices in future. The hardware's been admirable, particularly with a folio-style case and bluetooth keyboard. Great battery life. The display is limited, but the best as can be hoped for.
But the limitations on what I as a user can do drive me bloody bananas.
It's a very short drive, and an entirely uninteresting challenge.
Google, Samsung, and Logitech specifically have fucked this up hard and irretrievably.
I learned programming with JRuby SL4A on my smartphone. I can't imagine anyone doing this today. Gingerbread is without a doubt my favorite Android version. You had so much freedom back then!
Agreed then. I'm a developer and I can't see myself developing on a mobile phone operating system anytime soon. But I still like my Android phone for taking notes, pictures, syncing PDFs and reading my mails.
It's just two different use cases and different security/freedom tradeoffs. Not sure if I'd call Android a general purpose operating system.
That's a great point. Thinking back to the introduction of iOS and Android, iOS was appliance-like in that it was tailored to one use case (phone), while Android felt like a general-purpose OS that just happened to run on a phone.
As you point out, the benefit of Android was never quite taken advantage of.
However, Google's upcoming Android laptops will hopefully push the issue to the fore. It would be amazing to have a more powerful alternative to iOS on the iPad Pro, more powerful in ways we notice everyday, rather than just being more powerful on paper.
The sad thing is that back when 3.0 (Honeycomb) shipped, most of the 10" or so Android tablets included a full size USB-A port. But then came 3.1, and the introduction of the above permission, and basically the major selling point of said port evaporated (i have a Toshiba Thrive sitting here that i basically shelved after said change).
If we observe Windows tablets, with the MS Surface at the forefront, many of them come with a easily accessible USB-A port (I recall Gigabyte tried to sell a tablet that came complete with a ethernet port even, but i think that series has since been discontinued).
What worries me is that Google introduced this change to placate big media. Because around the same time they made the big announcement that people could now buy movies and music via the Android Marketplace (later renamed Google Play).
It's not to placate big media, but to increase security, as others have pointed out.
But the bigger point is that I don't think it's just the USB port that limited Android's flexibility. Android was supposed to be a more flexible, more powerful iOS. That didn't play out in ways the average end user cares about.
What advantage does a A-port have over the current micro ports in a tablet? And now the new C port is slowly gaining more support, I bet the A-port will slowly vanish completely, or am I missing something here?
Counter-intuitively, those big fat USB-A sockets have a much lower minimum-cycle specification compared to Micro-B or USB-C ( 1500, 5000 and 10000 respectively ).
> Android felt like a general-purpose OS that just happened to run on a phone.
And that was its big issue. They used the firmware model for a general purpose OS. This keeps Android from having the simple install models we've come to expect with Windows/some Linux distros/MacOS. I wrote a thing on this a while back:
Agreed, but my point was intended more in terms of what apps can do. Full access to USB, multitasking, users can install apps outside Google Play, a variety of hardware rather than just one or two models Apple deems good -- all these are advantages of Android when it comes to tablets, laptops or other devices to get work done. But the ecosystem hasn't evolved to take advantage of these, so the benefits are lost.
Note that Chromebooks are similar (and Android 7 adopts the update strategy of ChromeOS). There you have two system partitions, one in use and one on standby. A system update gets applied to the partition on standby, and on next reboot it becomes the used partition (unless the boot is deemed faulty).
BTW, event thought Chromebooks gets updates all the time the kernel and drivers are the same one as when they originally shipped. This means that older Chromebooks will not be able to run Android apps, as it is done using kernel provided containerization.
Recently built kernel. Unless things have changed from a few years back (when I last played with it), there are multiple (3) kernel partitions in ChromeOS:
...and you can manually select between them by using the "cgpt" command from the shell:
So on an ARM device, you could say:
sudo cgpt add -i 6 -P 5 -S 1 /dev/mmcblk0
If I'm not mistaken, this would mean to set partition 6 (a kernel) with a priority of 5 (compared to other partitions at boot), successful flag set to 1 on mmc block device 0-- (the internal mmc, where mmcblk1 is the external sdcard). I think if that kernel fails, that flips the successful flag to 0 and it falls back to the next priority kernel on the reboot. But like I said, it's been a while so don't quote me.
Also, if you weren't aware, to get into the shell:
ctrl-alt-T
shell
sudo bash
cgpt --help
if you play with cgpt, be VERY careful. Also, if you're thinking of replacing kernels or whatnot, be aware that on most (all?) devices, the partitions are signed, so you'll have to turn off any checks first.
Maybe they meant the major version number of the kernel wouldn't get an upgrade, though I suspect maybe performance/memory limitations are the real issue. It may be possible to backport whatever features are missing to an older machine's kernel and see...
Does every vendor have their own image, or is there one universal image for chrome laptops? If it's the former, can you just put a stock image on it, or does each vendor embed their drivers?
If you can unlock your bootloader, you can build your own version of chromeos and the kernel, but trust me, it's not as good. You'll have a chromium-based OS, not chrome based-- it's a lot like the difference between Chromium vs. Chrome in Linux, only affecting the whole OS.
I haven't done it in a few years, but I imagine that with the Android integration, even if it builds, you'll have more of a stock AOSP experience sans any Google cloud features. Good for freedom and privacy, but if you're bothering to replace the OS like that actual Linux may be a better call.
But if you go for standard Linux, you may run into issues with hardware support, especially graphics acceleration... just sayin'. The closed-source graphics drivers written for ChromeOS may not play friendly with Xorg or whatever.
Aside from potential issues w such blobs, I don't see any reason you couldn't unlock the bootloader and try updating your own kernel...
Yea I know a few people who attempted open-source (mostly; drivers are still usually closed) phones sans Google/Amazon stores and services. They'd use F-droid/K9-mail/OpenStreepMaps/OwnCloud, etc. They mostly work, but you do lose a lot of the android ecosystem. One of my friends gave up after a year and went back to the Play Store/Gapps because she started writing her own Android apps to make up for what she was missing and just didn't have the time for it.
I didn't realize ChromOS was in the same boat. That's really shit. In traditional Linux, a lot of drivers get merged right into the tree. Even for proprietary drivers/blobs, we have linux-firmware. For the most part, the initrd files on Arch/Debian/Ubuntu can load a lot of modern hardware.
I wish Google Android/Chrome devs would get their shit together and stop this individual build madness. An initrd full of drivers and linux-firmware do not take up that much space, and many phones now have the footprint of tiny laptops vs the old <8GB tiny flash roms.
Google wields a heavy hand with their (no-so-)open handset alliance (OHA). They can get manufactures to at least commit their blobs to a standard google-firmware package and keep a fork of their Kernel that builds all major drivers into a standard initrd package. Manufactures could always strip out all the crap for their custom ROMS, but this would allow AOSP to just run, out of the box, like Windows 10 or Ubuntu, on a large chunk of hardware.
Google's decisions in Android structure feel asinine.
I think it's not so much as the vendors of the graphics card and such that only released closed blobs to go with the open drivers in the kernel. And while they may work with say, ChromeOS, getting them to work on Linux isn't as straightforward. Android has a similar issue, though most of the time people aren't jumping from Android to another OS..
The first thing I do when I start a new Android app project is copy and paste this list-of-all-permissions into the project. This way I don't have to deal with any of the permissions related stuff until I have a working MVP. Once you have a MVP it's pretty easy to pin down the exact list of all the permissions you actually need in one go.
On a related note, there's some research[0] into parsing the Android OS source code and coming up with a mapping of "API call => required permission", and by apply this mapping to the source code of your own app the list of required permissions can be generated automatically. What do you guys think of this approach?
Seems like Android Studio should do exactly that kind of static analysis and warn you if your manifest specifies too many or too few permissions. There have been a few cases of companies releasing apps with catch-all permission requests like you recommend, and then facing a minor PR crisis as reports of the app's suspiciousness go viral.
This should be less relevant for apps using post-marshmallow-style permissions which don't need to be granted on install.
Static analysis will require too many permissions because of limitations on the tractability of the analysis (the Halting problem). Instrumenting is more reliable for a minimal set but isn't necessarily complete.
> coming up with a mapping of "API call => required permission"
Surely that must be part of the documentation of each API call, right? Like, "You must enable android.permission.X or this call will fail"? If it is, why not just scrape the documentation, and if it's not, how does anyone develop for Android?
The linter will give you warnings on some permissions.
But some of the permissions listed can't even be used without system permission, meaning your app has to be signed with the same keys the OS was (iirc more recently I've seen a device that didn't need this) and installed in a special system directory. Permissions like getting the users local MAC address...
I don't get the logic of doing this. For one thing, with the new runtime permissions model, introduced in Android 6, you need to request the permission from the user at runtime rather than in advance (in the play store when the app is installed).
So starting with Android 6, the user can say "no way" to granting a permission when asked, or at any time after installation (via the app settings menu), and the app has to gracefully notice and/or handle the lack of permission without crashing or otherwise screwing up. This means the app must be designed where the permissions-related stuff can be called asynchronously. I wrote a bit about this in my question here:
If just you start writing the app with every permission granted you're potentially going to have a huge headache when you go back to pin down the permissions you'll actually need-- now you need to go back and revise the logic so it can handle possible denials. Probably wiser to do that as you go, no?
And that's just the base functionality-- there's a UI question too that would benefit some advance-thinking. Do you want to hit the user with a huge list of permissions the first time they launch the app? Or maybe only in groups when they do key operations. Or perhaps individually. This is a question that may be informed by an early understanding of what permissions will be needed, so you know when to ask and what to do if denied.
At my company (MixRank), we do static analysis on apps for business intelligence. We've collected lots of data on permissions, SDKs, integrations, frameworks, etc. If anyone has any interesting queries they'd like me to run, I can give it a shot.
Here's the most popular permissions we've identified:
Iirc, since Android 6 (though really introduced in a earlier Play store update) quite a number of the network related permissions is accepted by default.
This because Google switched to putting different permissions into bins, and the networking bin is accepted by default. Note also that these days a user is only notified if a update introduces a new bin requirement, not on every permission change.
See digi_owl's comment. In addition to that, Google Play Games does inter-process communication with Google Play Services which essentially has unfettered permissions.
I am not sure what the point of this list is ?
Aren't the runtime permissions the only ones we really need to think about going forward ?
We still need to declare the 'normal' permissions, but they will be mostly invisible to the end-user, no ?
The others ones are still there but pretty much an implementation detail now for Marshmallow apps (I know M+ is a tiny market share at the moment, but it will only increase).
Why is this list "all" permissions? It contains non-Google stuff like Amazon permissions, yet not for other platform like Symbol permissions. I'm confused.
Those other permissions were in there because whenthe script was gathering all the perms, it also gathered the JuiceSSH perms and other app permissions. I wrote a script to filter out everything but stock perms, and now it should be right. ;)
Android has both high-level IPC via Intent filters and low-level IPC via bound Service objects. Neither create instability. ACTION_SEND is widely implemented without creating instability. But other verbs are underutilized: Setting calendar events, picking contacts, etc. ACTION_EDIT should be almost as common as ACTION_SEND. Making a cooperating suite of apps is a huge missed opportunity in Android. Meanwhile I see plenty of bloaty apps that are unstable because they are large and monolithic.
Low-level IPC is practically inapplicable to apps made by different creators working together. Not to mention it's no dream to work with.
I work with hardware that comes with stock AOSP, and getting a "daemon" style service to run from boot without closing took several workarounds, even though it should have been as simple as "START_STICKY" with a foreground service Android's Service model is very clearly not meant to support such a simple usecase. The most reliable way is actually to modify the image because only system services are supposed to be allowed to do that.
Working with services that aren't reliably started can also be bad for UX even if you don't have the usecase I had of needing a daemon because there might be a high cost associated with starting up. People also don't want every service showing a notification to stay alive.
After trying to model this complex device management system I was working on in nice contained pieces we could maintain separately, I was forced to stuff it into one monolithic app. Performance improved because we no longer needed workarounds to keep the multiple services alive, just one was enough, and we only needed one process to stay alive (a process which is always second from the top in recent usage because our hardware only needs to run our app and a 2nd party one).
Intents are unstable because no one follows the standards for verbs properly. Samsung's built in apps are notorious for crashing if you try to use extras. Facebook won't crash, but it won't respect EXTRA_TEXT or EXTRA_SUBJECT properly because they only want you sharing a URL. Pinterest crashes on sharing some images that other apps don't.
I'd almost go as far as saying you can find a crash report that's app-specific for any major app (Gmail, Facebook, etc.) that you'd expect to see receive a share intent by googling "<insert app name> android intent crash". It's almost always something with the app that's taking the intent not respecting the intent contract properly.
It seems like 80% of your trouble comes from trying to subvert the "your service won't start until you use it" solution to the "everybody is lazy and/or anti-social and wants to start their service on boot" problem. In other words, Google intended to make the life of an app author who wants this extremely difficult and would have suggested that they attack the "because there might be a high cost associated with starting up" problem instead. But, yeah, if it is your device with your AOSP build, and you really really have The Most Important Service, go ahead and compile it into the system.
On top of all that, the usual reason there is a "high cost to starting something" is that it hits a server and hasn't cached the data it needs. The OS can't solve that for you.
That was really a digression of my main point of intents forming an unstable API but our problem was 100% subverting your service won't start until you use it, but Google's approach is insanely heavy handed. A saner solution would to be to give a permission for daemon style services that comes with a warning to the user about battery life and network implications.
Our service really is the most important service on the device because if our service goes down the device is essentially "bricked" (these are embedded android devices so we lose visibility on the installation), but adding our service to the image means managing images for every device variation we use (and some of those device's manufacturer's won't be happy to have someone else managing said images since it means more work for them [build image, send it to us, we modify it, send it back to them, they use it vs just building an image and using it]).
It's a unique use case, but it's not hard to imagine more common software that could take advantage of daemons, even if it's just to provide smarter background processing than the "all-or-nothing" defaults provide (like START_STICKY). Besides being rather unique to our use case, I'd also say it doesn't have to do with apps from different creators working together...
And I don't think the network is involved most cases of expensive services, because the OS (or more specifically, Google's services on most end user devices) already help solve that with things like the GCMNetworkManager and ConnectivityManager callbacks for optimizing network access.
Ok I see what your situation is. And I'm curious, because this is sort of my thing. I don't think allowing greedy services with a big red warning would be a good solution for you either because your users would tire of seeing the warning, even if only at boot.
I would put a service-starter service in the device images. I see that might be a problem, too, because it seems like you are only "lightly embedded," with multiple hardware platforms. But this could be a really lo-impact thing for your hardware partners and relatively clean. Alternatively, provide a modified launcher, if you are not already replacing the launcher with your own embedded app, that tickles the service on startup. There are probably other advantages to having your own Home app if I understand your situation correctly.
Google has to be heavy handed because too much mobile development is crap, and a low-bidder contract development shop wouldn't hesitate to take the anti-social way to an implementation if they could. The road to hell is paved with cheapass outsourcing.
We experimented with a lightweight bootstrap service, but there was too much resistance from the manufacturers.
It'd pretty much require changing our contract to have much more expensive terms because from their pov it crossed the line from them providing pre-installed software (our apps) , to them providing custom devices ("our image").
I also tried some tricks with replacing the launcher since we have full root access, but the launcher process was getting killed almost as often as our custom services.
Since I moved to a single-process model I've had fewer killed services, but we still have the AlarmManager kicking them off just in case.
A lot of the moves Google's been making, from shutting down file uris for content providers feel like they're meant to shut down the "easiest way out for developers", things that are easy for devs, but bad for the average mobile user, but they're also hurting Android for other usecases. I guess the plan is to push Brillo for that, but being able to leverage Android's ecosystem on embedded has some advantages
You don't need any special access to replace the launcher. They just need to set your Launcher as default as part of the pre-load. Since I don't know your product it's a little hard to say but the combination of a Home app that check on configuration sanity and a watchdog, which it sounds like what you are using AlarmManager for should do you.
No, we do something like "bespoke" digital installations for different brands, sometimes it's simple digital signage, sometimes it's stuff that's a little more interactive, but we try and centralize the apps involved on a platform we built on one specific Android device which has now spread out onto different models for certain clients that had special requirements like large touchscreens
Yes they can be. Android puts them into 'bins', e.g. all the network-related ones together. Importantly, when an app upgrades and the new version wants new permissions, these are silently granted if they are the same bin as existing granted permissions.
Therefore, from a security perspective, there are far fewer coarser permissions.