WAI
Status Update
Comments
ar...@google.com <ar...@google.com>
na...@google.com <na...@google.com> #2
Your request mentions “custom broadcasts used by individual apps”.
The documentation states that implicit broadcasts are broadcasts that do not target an app specifically. As such apps can continue to register for explicit broadcasts in their manifests (that target individual apps). Alternatively the suggested approach going forward is to use JobScheduler if the apps previously registered for implicit broadcasts.
If you would like more information, please clarify which custom broadcasts (implicit vs explicit?) you are referring to. A snippet of sample code would also be helpful.
The documentation states that implicit broadcasts are broadcasts that do not target an app specifically. As such apps can continue to register for explicit broadcasts in their manifests (that target individual apps). Alternatively the suggested approach going forward is to use JobScheduler if the apps previously registered for implicit broadcasts.
If you would like more information, please clarify which custom broadcasts (implicit vs explicit?) you are referring to. A snippet of sample code would also be helpful.
mm...@commonsware.com <mm...@commonsware.com> #3
I believe that the question is about custom implicit broadcasts. Many apps have an SDK of sorts, of the form of custom implicit broadcasts, where they tell other developers to listen to those broadcasts to find out about state changes within the app. Music players, for example, send custom implicit broadcasts regarding track changes. In some cases, such as the music player example, the registered receivers for those broadcasts will be registered via registerReceiver(), in which case there is no O problem. Other times, the receiver will be registered in the manifest, in which case our interpretation of the documentation is that the app-specific SDK will break on O.
te...@gmail.com <te...@gmail.com> #4
componentid:190923 status:open
Rv...@nxt.ru <Rv...@nxt.ru> #5
I am referring to custom implicit broadcasts.
Sorry, I was unable to find emulator image with Android O, so I can' provide self-contained project for reproduction.
When my apps sends a broadcast like this
final Intent intent = new Intent("com.example.SOME_EVENT_HAS_HAPPENED");
intent.putExtra("com.example.ADDITIONAL_INFORMATION", parcelable);
sendBroadcast(intent);
I expect that it will invoke BroadcastReceivers of all apps, that have broadcast filters for that action in their AndroidManifest. This used to work before Android O.
Could you explain how to use JobScheduler to schedule a specific job in multiple different apps with some arguments? Unless such thing is possible, I don't think that JobScheduler is a viable replacement for broadcasts.
Sorry, I was unable to find emulator image with Android O, so I can' provide self-contained project for reproduction.
When my apps sends a broadcast like this
final Intent intent = new Intent("com.example.SOME_EVENT_HAS_HAPPENED");
intent.putExtra("com.example.ADDITIONAL_INFORMATION", parcelable);
sendBroadcast(intent);
I expect that it will invoke BroadcastReceivers of all apps, that have broadcast filters for that action in their AndroidManifest. This used to work before Android O.
Could you explain how to use JobScheduler to schedule a specific job in multiple different apps with some arguments? Unless such thing is possible, I don't think that JobScheduler is a viable replacement for broadcasts.
ar...@google.com <ar...@google.com>
na...@google.com <na...@google.com> #6
Thank you for reporting this issue. The engineering team is reviewing this and we'll update this issue with more information as it becomes available.
ha...@google.com <ha...@google.com> #7
Hi, thanks for your feedback!
I do understand your concern, however this is not something we want to allow.
To help understand what is going on, I need to clarify that the purpose of this change is *not* directly related to battery use, but rather to address long-standing issues we have had in the platform where devices that are under memory pressure can get in to bad thrashing states. Very often these states are due to broadcasts: some broadcast or broadcasts are being sent relatively frequently, which a lot of applications are listening to through their manifest (so need to be launched to receive it), but there is not enough RAM to keep all of those app proceses in cache, so the system ends up continually thrashing through processes each time the broadcast is sent.
This is an issue regardless of whether the device is currently plugged in to power. In fact, this can more frequently be an issue on Android TV devices (which are always plugged in to power) because they tend to be fairly tight on RAM!
For this reason, we really don't want to allow general implicit broadcasts, since these can have an arbitrary number of apps listening to them that nobody really has control over. Our approach for imposing this restriction on the system has been to start out not allowing any such broadcasts as a global policy, and then only bring back in a very small handful that we have identified as particurily useful and not disruptive. (A good example being BOOT_COMPLETED -- it is very useful, and though it has a ton of apps that generally listen to it, we know it will only happen a single time, at system boot, so not possible to have a continual impact. Many other exceptions are based on the fact that they happen purely as part of a user interaction -- such as LOCALE_CHANGED -- so we are okay with the system needing to potentially thrash through apps in order to complete what the user has said they want to do.)
Yes it is true that developers can manually write code that will do inefficient things, and changing the policy for how implicit broadcasts are dispatched won't prevent them from writing bad stuff. However, it has become pretty clear that this particular facility is a landmine that both system and app developers step on (again from years of looking at devices in bad states and seeing this pattern of frequent broadcasts causing a large number of apps to launch for each one causing the system to thrash trying to deliver them), so going forward we don't want it to be a pattern that we encourage. We already have much better patterns, such as explicitly registering a PendingIntent to monitor for a specific set of changes one is interested in, that are commonly in use by the system, which we recommend over open-ended implicit broadcasts.
I do understand your concern, however this is not something we want to allow.
To help understand what is going on, I need to clarify that the purpose of this change is *not* directly related to battery use, but rather to address long-standing issues we have had in the platform where devices that are under memory pressure can get in to bad thrashing states. Very often these states are due to broadcasts: some broadcast or broadcasts are being sent relatively frequently, which a lot of applications are listening to through their manifest (so need to be launched to receive it), but there is not enough RAM to keep all of those app proceses in cache, so the system ends up continually thrashing through processes each time the broadcast is sent.
This is an issue regardless of whether the device is currently plugged in to power. In fact, this can more frequently be an issue on Android TV devices (which are always plugged in to power) because they tend to be fairly tight on RAM!
For this reason, we really don't want to allow general implicit broadcasts, since these can have an arbitrary number of apps listening to them that nobody really has control over. Our approach for imposing this restriction on the system has been to start out not allowing any such broadcasts as a global policy, and then only bring back in a very small handful that we have identified as particurily useful and not disruptive. (A good example being BOOT_COMPLETED -- it is very useful, and though it has a ton of apps that generally listen to it, we know it will only happen a single time, at system boot, so not possible to have a continual impact. Many other exceptions are based on the fact that they happen purely as part of a user interaction -- such as LOCALE_CHANGED -- so we are okay with the system needing to potentially thrash through apps in order to complete what the user has said they want to do.)
Yes it is true that developers can manually write code that will do inefficient things, and changing the policy for how implicit broadcasts are dispatched won't prevent them from writing bad stuff. However, it has become pretty clear that this particular facility is a landmine that both system and app developers step on (again from years of looking at devices in bad states and seeing this pattern of frequent broadcasts causing a large number of apps to launch for each one causing the system to thrash trying to deliver them), so going forward we don't want it to be a pattern that we encourage. We already have much better patterns, such as explicitly registering a PendingIntent to monitor for a specific set of changes one is interested in, that are commonly in use by the system, which we recommend over open-ended implicit broadcasts.
un...@watchguard.com <un...@watchguard.com> #8
Hi. I understand your explanation about the RAM related problems the platform has, and how it becomes more relevant when several apps need to be started due to a broadcast they are listening to. I also understand that you're trying to find solutions to this problem, and one of them could be to avoid having to launch several apps at the same time when such a system event happens.
But I can't understand why you don't give a valid alternative for this situation instead of directly breaking the legit apps, that provide a functionality based on one such system events, and which the users have decided themselves to install because they wanted that specific functionality.
You don't want the solution to be having implicit broadcasts? Ok, no problem. But give the apps an alternative to the implicit broadcasts for the functionality you're breaking! Apps that have been in your Market for YEARS, with more than a million users are having part of their functionality broken due to your platform RAM problems and this radical decision. I'm not asking for implicit broadcasts, i'm asking for a solution we could migrate to if you are deprecating (and removing) that functionality.
Possible solutions? I don't know the internals of your platform to give you a solution, but i'm sure that there's a better one than directly breaking applications.
You might extend the JobScheduler API to be able to subscribe to those events (the ones that fired the implicit broadcasts), and this way you could control when to launch those apps in a more RAM friendly way, in a reasonable time window.
You can provide a way for the apps to ask the user for higher priority for a specific system event listener, and defer in time the call to those apps that do not need have high priority (like you've don with "Doze").
You might allow the user to decide if he want's one app to run without restrictions. Let the user decide.
BTW, could you give me a link that explains how can I be notified of a new app installation/remove using a PendingIntent or the JobScheduler?
Please, give us developers a way to migrate from implicit broadcast to another RAM friendly solution, without breaking our apps.
But I can't understand why you don't give a valid alternative for this situation instead of directly breaking the legit apps, that provide a functionality based on one such system events, and which the users have decided themselves to install because they wanted that specific functionality.
You don't want the solution to be having implicit broadcasts? Ok, no problem. But give the apps an alternative to the implicit broadcasts for the functionality you're breaking! Apps that have been in your Market for YEARS, with more than a million users are having part of their functionality broken due to your platform RAM problems and this radical decision. I'm not asking for implicit broadcasts, i'm asking for a solution we could migrate to if you are deprecating (and removing) that functionality.
Possible solutions? I don't know the internals of your platform to give you a solution, but i'm sure that there's a better one than directly breaking applications.
You might extend the JobScheduler API to be able to subscribe to those events (the ones that fired the implicit broadcasts), and this way you could control when to launch those apps in a more RAM friendly way, in a reasonable time window.
You can provide a way for the apps to ask the user for higher priority for a specific system event listener, and defer in time the call to those apps that do not need have high priority (like you've don with "Doze").
You might allow the user to decide if he want's one app to run without restrictions. Let the user decide.
BTW, could you give me a link that explains how can I be notified of a new app installation/remove using a PendingIntent or the JobScheduler?
Please, give us developers a way to migrate from implicit broadcast to another RAM friendly solution, without breaking our apps.
ta...@gmail.com <ta...@gmail.com> #9
Aren't they going to still work on Android O if you just put the component name of the BroadcastReceiver (making it explicit) along with the action?
mm...@commonsware.com <mm...@commonsware.com> #10
#9: Yes, explicit broadcasts work. As a sender of broadcasts, therefore, you can work around the limitation by performing a manual fanout, iterating over the registered receivers and doing N explicit broadcasts rather than one implicit one. See https://commonsware.com/blog/2017/04/11/android-o-implicit-broadcast-ban.html for more. This is not ideal, as it will result in the same process churn that #7 indicates is the reason for the O behavior change.
Description
I believe, that such broadcasts should not be subjected to Android O limitations for reasons explained below.
Most importantly, those limitations are completely pointless for third-party broadcast senders. As long as PackageManager still provides means to filter apps based on manifest details, people will be able to send targeted broadcasts, period. They might have to manually iterate over the list of targets, but authors of poorly written apps (who, I believe are targeted by these changes) won't be stopped.
If you simply want to avoid round-trip via system service for such broadcast, you can just implement manual iteration over broadcast filters within existing Context#sendBroadcast API.
I also don't believe that third-party implicit broadcasts contribute to battery issues to any visible extent. Android builtin framework components are guilty of holding permanent "wakelocks", so they are the ones causing most performance issues. Third party apps already has to be alive (via wakelock or otherwise) in order to send a broadcast. If they abuse broadcast receivers to send "second order" broadcasts, prohibit sending nested broadcasts from within BroadcastReceiver receiver wakelocks.
If you truly believe, that custom broadcasts may be an issue, please make sure, that you aren't misguided by your statistical data. Sure, broadcasts and their wakelocks are highly-visible… But aren't foreground components too? Aren't they responsible for like 90% of battery consumption? But foreground components perform useful work! They are visible to user, aren't they? But aren't broadcasts often "visible" too? If my broadcast is sent by my foreground app as means of starting work in service or another foreground app, should it really be restricted in any way? Can I please give those apps my blessing as long as my own app is in foreground? I'd rather prefer framework developers to work on better mechanisms of wakelock delegation, not scrapping "problematic" pieces of your Binder system.
If BroadcastReceiver wakelocks are so much of issue, give apps better control over those wakelocks and/or lower the time limit for holding them. Bad design of IPC, relying on everyone holding a wakelock for lengthily amount of time, is a poor excuse for removing the IPC completely. Personally, I would prefer being threatened with my process being killed on short notice, to not having it running in the first place.
If apps perform lengthily tasks in BroadcastReceivers, such as reading/writing huge files, punish those apps, not everyone. Or better yet, give people means to measure/avoid such performance issues. When will Google finally warn people, that creating a SharedPreferences instance always involve disk access?!? Even disk writes should not be much of issue, as far as battery is concerned: the data is usually stored in OS disk cache anyway. How often does ext4 flush everything to disk in Android? How often does vFAT driver do? Since apps don't usually die themselves, you can flush their stuff when necessary, not every N seconds or each time an apply() is called. Simply fiddling with flush rate and dirty page ratio should give you better battery savings than killing off entire broadcast system. Has this already been done?
I would like to see any kind of data proving that app own broadcasts constitute significant performance issue. If such data exists, Google Play should contact authors of guilty apps (which should be few) and requests them to directly resolve their issues. For some reason, I suspect, that the biggest perpetrators in this case will be Google's own Play Services. But lack of internal communication within Google is not a reason to remove crucial functionality from platform.
In addition to reasons above, please remember, that Android is not always in unplugged/battery-starved state. Do such "amazing" optimizations really make sense for Chrome OS, notebooks, media players or pretty much anyone else, when their device is plugged to AC? You are crippling entire OS for sake of single specific scenario. Is it important? Sure. But blindly optimizing for it *forever* sounds too much like desperate move. Isn't there still a lot that can be done elsewhere? You can force processes to single core via affinities. You can punish overly disk-happy apps by lowering their IO niceness. Most importantly, you can educate people, which, I believe, still has a long way to go. How many lint warnings currently cover battery usage?
By forcing people to use manual broadcast dispatch you are reducing your degree of your control, not improving it. I don't think, that explicit broadcast filters + statistics are worse than just statistics for the same reasons why properly configured static IP routing can not be worse then fully dynamic one. Should not you use that static data in manifests for optimizing instead of forcing people to remove it?
For reasons listed above, please re-consider imposing broadcast limitations on custom broadcast in Android O.