I'm developing an Android app that is going to be embedded on a non-mobile device owned by our client, and used by our client's customers. My boss is envisioning a second app for the machine that runs in the background and sends data about the device to the backend periodically via a Service. I've employed this method, though I'm aware that it is imperfect because Android is prone to killing background services at will and at unspecified times, namely when it decides the service is obsolete or the system needs more memory.
That said, we are running the open-source version of Android (v5.1.1). I'm wondering if there are any options available to my OS team that aren't available for those building apps for the Google Android flavors, some way to remove those typical house-keeping mechanisms or auto-restart apps that have been closed?
Set android:persistent="true" on your <application> tag in the manifest.
The docs say:
Whether or not the application should remain running at all times — "true" if it should, and "false" if not. The default value is "false". Applications should not normally set this flag; persistence mode is intended only for certain system applications.
For this to work, your APK will need to be installed on the system partition. It may also need to be in the priv-app dir or be signed with the same key as the system (some of these things do; I don't remember for this specific case).
Note that your Application.onCreate() will be started automatically; your Service will not be started automatically. Not that you need it; when you're persistent, the Android system won't (normally) kill your process, so you can just run normal threads doing what you need to.
Finally, make very sure that you're not leaking memory. Persistent apps are killed very late (if at all..?) by the LMK, so it could have adverse effects on the performance or stability of your device.
You have 3 options here in my opinion:
Modify Android OOMKiller to exclude your app. Wouldn't recommend this.
Create a Java system service, that is started by SystemServer
Create a native C "app" (binary), that is started in one of the init.rc scripts. ( The daemon suggested by CommonsWare comment ). This can have the benefit of being able to be run as root if you need it.
Related
I was reading "Multitasking the Android Way" by Dianne Hackborn and found one sentence I don't quite understand (I bolded the puzzling part):
A common misunderstanding about Android multitasking is the difference
between a process and an application. In Android these are not tightly
coupled entities: applications may seem present to the user without an
actual process currently running the app; multiple applications may
share processes, or one application may make use of multiple processes
depending on its needs; the process(es) of an application may be kept
around by Android even when that application is not actively doing
something.
How is it even possible? To "present" an application to the user, we need a least one of its activities to be in resumed state, and for this we need the underlying Linux process up and running, right? Is she talking about the application launcher or something?
To "present" an application to the user, we need a least one of its activities to be in resumed state, and for this we need the underlying Linux process up and running, right?
There are a few ways in which the user can see an app's UI without the app having a currently running process, such as:
The app can have an app widget on the home screen
The app can have a Notification in the status bar, or on a Wear device
The app can have an entry in the recent-tasks list
My interpretation is that "applications may seem present" refers to something like these.
I have read the following statements here
By default, all components of the same application run in the same process and most applications should not change this. However, if one needs to control which process a certain component belongs to, he can do so in the manifest file. The manifest entry for each type of component element—<activity>, <service>, <receiver>, and <provider>—supports an android:process attribute that can specify a process in which that component should run. One can set this attribute so that each component runs in its own process or so that some components share a process while others do not.
I want to know in which scenarios a developer would like to do so and run different components in different processes and what advantage will he get by doing so?
Another statement that I have read is
The <application> element in the manifest file also supports an android:process attribute, to set a default value that applies to all components
Regarding the above statement I want to know Why would a developer do that, there is already one process associated with one application by default and all the components run inside that process.
Can anyone clarify these things for me as I am not getting any details on this anywhere else
thanks
Let us take the example of Google Chrome browser which has made best use of android:process attribute. Before that let us understand why multi-process architecture was considered.
Remember those age old days, when we were using co-operative multi-tasking operating system. There was one single process and applications used to run in that single process turn by turn. Problem with that architecture was, if one application misbehaves that single process dies off there by bringing entire system down.
Now a days modern operation system, run applications in their own processes. If one application misbehaves, the process hosting it dies off and does not affect rest of the system.
Same applies to the browser. If one web-page misbehaves, it brings down the entire browser there by making web-pages opened in other tabs unavailable. Hence multi-process architecture was built.
Separate processes are used for browser tabs to protect the browser application from bugs in the rendering engine. Each render process is run as an android service in separate process. This is done by using android:process tag of <service> element. Another important flag used for rendering engine process is android:isolateProcess. This flag ensures render process does not have access to the system resources like network, display and file system, there by making the browser application highly secure.
Here is the snippet of chrome's manifest file:
<service android:name="org.chromium.content.app.SandboxedProcessService0" android:permission="com.google.android.apps.chrome.permission.CHILD_SERVICE" android:exported="false" android:process=":sandboxed_process0" android:isolatedProcess="true" />
Here is the output of adb shell:
USER PID PPID VSIZE RSS WCHAN PC NAME
u0_a14 12926 317 694380 102828 ffffffff 00000000 S com.android.chrome
u0_i16 26875 317 590860 59012 ffffffff 00000000 S com.android.chrome:sandboxed_process5
u0_i17 27004 317 577460 47644 ffffffff 00000000 S com.android.chrome:sandboxed_process6
The element in the manifest file also supports an
android:process attribute, to set a default value that applies to all
components
By default the name of the application process will be the package name specified in <manifest> tag. This can be overridden by specifying the name in the android:process attribute of the <application> tag. One use case : if multiple applications want to run in the same process, provided those applications are signed by same certificate and share the user ID.
If the name of <android:process> starts with :, it becomes private to that application, as in case of chrome's rendering engine (com.android.chrome:sandboxed_process5). It implies applications except com.android.chrome cannot communicate with this rendering engine.
If the name of <android:process> starts with lowercase character, it becomes global process. From docs:
This allows components in different applications to share a process,
reducing resource usage.
Summary of benefits:
To improve overall application stability (crashes / hangs). One service process crash does not bring down entire application.
Security by preventing access to the rest of the system.
Reduce resource usage, by running component in a process and sharing it among different applications.
Basically you should be able to separate the concerns and decide whether it makes sense to apply multi-process architecture.
Update 1: Adding #Budius comment
Each process have only a certain amount of memory available. In the app I work at, we do computational intensive processing in large memory arrays. Those computational we always fire in a separate process to make sure we'll have enough memory for the whole thing to happen and not crash with OutOfMemory.
The reason one might want to do this is because Android can shut down your application process to free up memory in the system any time it wants to, and you may want to mitigate the situation.
Suppose you have a really, really important piece of code that takes a long while to complete that would be very bad to kill in the middle of it working (for instance, a financial transaction in bank software). Putting this piece of code in a Service that runs in a separate process from the rest of the application code will ensure Android doesn't kill your Service that is potentially still running after the user exited your application.
From the docs:
When deciding which processes to kill, the Android system weighs their
relative importance to the user. For example, it more readily shuts
down a process hosting activities that are no longer visible on
screen, compared to a process hosting visible activities. The decision
whether to terminate a process, therefore, depends on the state of the
components running in that process.
You can read more here
In general, a Service is used when you expect a non-UI task to take a fairly long time to complete. An Activity that does not remain in the foreground can in all probability be terminated by the OS, while a Service can continue to run indefinitely.
A Service is created in a separate process when you don't want the garbage collector to affect its working. The garbage collector will, in that case, affect only the application process. Moreover, a Service in a separate process has the added advantage that it will consume slightly less memory than what it would if it were in the main application process.
The Service that you declare in a separate process can be either private to the application:
<service android:process=":my_private_process"
or it can be global:
<service android:process="my_global_process"
In the latter case there is no colon prefix. A Service in a private process can only interact with your application, while a Service in a public process can deal with other applications as well. This is mainly when a Service should be used in a separate process: when you want your application to share data or functionality with other applications, and to do it in the background without being disturbed by the OS or the GC. To quote the documentation:
This allows components in different applications to share a process, reducing resource usage.
I'd like to make a system level service in android.
But i need to edit SystemServer.java in the framework. Is there anyway to 'reflect' into this to get it done ?
The line i'd like to add is:
ServiceManager.addService(“TestServiceDescription”, new
TestService(context));
Then others would be able to call my service the same way they call other android system level services. I would supply the AIDL of my service to the clients.
No, as #AleksG pointed this is impossible. The reason for this is that System Server is a privileged component in the system, i.e. it has access to critical system resources. Thus, a user application should have no possibility to be reflected into the system process. Otherwise, the security and reliability of the system will be questioned.
In my app, I'm using a contact sync adapter, but it has a lot of information that it shares with the main app. There are settings that the adapter needs to work proplery (like login information and if the user changes any sync settings), so I currently have it running in the same process, and it communicates with the main ap using getApplicationContext(), and then I have some shared variables in the Application that the sync adapter is using during the sync process.
But in the training document, and a few tutorials online, the sample adapter is set up to run in its own process -- it's using android:process=":sync" in the manifest. Is that necessary? And if it does run in a separate process, how can I communicate back to the main app?
In our context, due to fast searching requirement, we are using remote service to hold a huge database in memory.
The reason we are using remote service, instead of local service is that, we believe running the service in separate process, will make us harder to hit maximum memory per process limitation (The limitation is vary based on different devices and OS version).
In our initial design, we are using AIDL. Later, we switch to Messenger. I cannot recall the reason behind. I will check back our source code history log to figure out why. But, I think it is mostly, Messenger is less complicated than AIDL, and we do not need the multi-thread capability provided by AIDL.
Running Service in its own process may be helpful
1) if you want your service to withstand your main app's process destruction (but START_STICKY is more than enough for that case),
2) if you'd like to designate this process for all "sync" tasks of your application (as stated in the tutorial),
3) if you want other apps to use your Service.
To communicate with the Service running in separate process, you use Bound Services.
However, running Service in separate process increases the complexity of communicating with it, so consider if any of cases mentioned above relates to your app purposes.
I think it should be separated, but it's not required.
In general, separating a Service process is well worth to consider if it may be used independently from system components or other applications. In this perspective, the lifecycle of the process should be managed independently from other components such as Activity in the same app, so Android can mark which process is currently used easily and precisely to decide which process to be killed in case of a memory shortage. Also the service can keep running even if the front activity crashed unexpectedly.
It's hard to maintain sharing data between separate processes. For login credentials and preferences, I guess you may go with a combination of SharedPreferences and OnSharedPreferenceChangeListener.
When the application starts, it may cache different things, in particular for the UI. By splitting the sync logic in a different process, you allow the UI process to be killed when the device is running low in memory, which will free these UI caches.
Hence, this technique is primarily of interest to apps that run services for a long time. Typical examples:
the service that plays music in a music app
the service that uploads the video in Youtube
However:
this increases the complexity of the app
if done incorrectly, it can actually increase the overall memory footprint of the app
I am currently working on an Android project that monitors what applications a user is running and cross-checks the corresponding processes with a whitelist stored internally on the device.
In order to make this work, I need to know what the default or system processes for the device are so I can add them to the whitelist. That being said, I have a few questions I was hoping you might be able to answer:
Is there a way to differentiate between a default/system process that MUST be running, and a process that belongs to an app on the device?
Are there different default/system processes depending on what phone/version of android the user is running?
If so, are those process names available somewhere for developer use? Or is there some other way to obtain them?
If I need to elaborate more please let me know, thanks for the help.
Let's say that you try ActivityManager and getRunningAppProcesses(). Iterate over that array of RunningAppProcessInfo objects and find those with importance of IMPORTANCE_FOREGROUND. If the docs are correct (haven't tried this), there should only be one process that is IMPORTANCE_FOREGROUND -- the one that is truly in the UI foreground.
(services can call a startForeground() method to get foreground priority, but I am guessing they have IMPORTANCE_PERCEPTIBLE)
You could then examine the pkgList of that foreground process and compare that against your whitelist.
However, this breaks down if:
Something pops up asynchronously (alarm clock app, incoming phone call, etc.)
An app that is logically in your whitelist has changes that affect its package name (e.g., developer released a "pro" app that a student paid for, and the whitelist only has the free app)
if the device has multiple visible items (e.g., Samsung's multi-window capabilities), if all visible apps are not IMPORTANCE_FOREGROUND
This at least gets rid of the problem of pure background stuff that the student cannot control, including your "default/system processes".
However, it requires you to continuously poll, which will be a serious detriment to battery life. That, plus the privacy implications, means to me that this app should, at best, only be used for exams, and should be something that the student can install shortly before the exam and remove shortly after the exam.
Well I think my team and I have come up with the best solution so far. After reading the Android Docs, we found that by using ActivityManager.getRunningServices() we can use the constant FLAG_SYSTEM_PROCESS to determine what processes are core system processes. Then all we would do is cross-check that with the total list of running processes to differentiate between them.