I am investigating about a custom system service for AOSP to provide a basic remote control (switching users and starting apps) for the system via network. It should be based on Android 9. For future portability, I would prefer to use rather high-level Java APIs, if possible.
I don't have much knowledge about Android yet on system level. It seems, at least a part of the functionality can be covered by communicating with the Activity Manager, which could be a good starting point.
Some of my questions:
is it intended at all, to have different system services to communicate with each other?
Provided this is possible, how can one system service use other service's functionality? Should this still go through HIDL/binder although all services live in the same process?
Is there an existing system service which does something similiar that could be useful as reference?
is it intended at all, to have different system services to communicate with each other?
Yes, that is intended.
Provided this is possible, how can one system service use other service's functionality? Should this still go through HIDL/binder although all services live in the same process?
HIDL over /dev/hwbinder is intended for HAL to System Service communication. Communication between System Services can still be done with AIDL over /dev/binder. I think you would typically use a services Manager class which will abstract Binder use anyway. This might not be a nice minimalistic example, but you have a look at how the Car service uses the TelephonyManager in CarAudioService.java.
Is there an existing system service which does something similiar that could be useful as reference?
You can have a look at the additional services in packages/services.
There are two type of system services:
1. Running in system_server: they are started in SystemServer.java; apps can call them by XXXManager(eg, ActivityManager); and they also provide some internal api which called by other services in system_server.
2. Running in apps which have system uid or platform permission: they are normal app services; they can do something that third app can't do; they are complied with android source, so then can call hide api.
Type 2 services can meet most needs. So I suggest you to choose Type 2 service. It's more easier to debugged and maintained.
Related
I'm trying to get a better understanding of the differences so I can evaluate if I should be implementing a System Service, or a Service. The differences that I have found from the docs are the following:
System Service
Started in SystemServer
Added to ServiceManager
Considered mandatory, and soft reboots the device on failure
More permissions? (Not sure what it can do that a Service can't)
Service
Initialized and started using an intent?
Is there anything else is different between the two? I'm modifying AOSP to include my own service, and any additional supplied information would be helpful in assisting me make a decision.
All system services are run in the same process called system_server.
There's a lot of things which system service can but service can't. system service usually has a higher and more specified sepolicy which normal apps will not have, for example(change NFC hardware parameters).
so if you want add you own system service, notice things above, if you code has a deadlock, you will affect all system services. and without a sepolicy, you service may still unable to access some resources.
Android Services
Android services are system component which allows performing a
longer-running operation while not interacting with the user.
Just like Activities, Service runs on Main Thread and has a life cycle but unlike Activity, Services do not have a UI.
Anyone can use & create Service or its direct subclasses IntentServcice in their Apps and it works pretty well.
Common usages are: Playing Media, Downloading files from the Internet, etc.
System Services
System services are a direct derivative of SystemService class. They reside in com.android.server packagein AOSP tree
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/services/
System Services also run in Main Thread so if you want to do some CPU intensive task then you much reuse HandlerThread architecture of AOSP.
What makes System service different from Android Services?
System Services are started by SystemServer hence they run as a System process which gives them additional privileges which normal Android Service will never get hence they are named name SystemService.
Example: You can't use Instrumentation to inject events in App other than yours because you will need INJECT_EVENT permission which is not granted to normal apps. SystemService can do that because they have elevated access.
The simple example of System Service :
package com.android.server.appwidget;
import android.content.Context;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.FgThread;
import com.android.server.SystemService;
/**
* SystemService that publishes an IAppWidgetService.
*/
public class AppWidgetService extends SystemService {
private final AppWidgetServiceImpl mImpl;
public AppWidgetService(Context context) {
super(context);
mImpl = new AppWidgetServiceImpl(context);
}
#Override
public void onStart() {
mImpl.onStart();
publishBinderService(Context.APPWIDGET_SERVICE, mImpl);
AppWidgetBackupBridge.register(mImpl);
}
#Override
public void onBootPhase(int phase) {
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
mImpl.setSafeMode(isSafeMode());
}
}
#Override
public void onStopUser(int userHandle) {
mImpl.onUserStopped(userHandle);
}
#Override
public void onSwitchUser(int userHandle) {
mImpl.reloadWidgetsMaskedStateForGroup(userHandle);
}
}
It really depends on what exactly you want to implement. I generally prefer to add functionality over modifications to the Android platform so I don't recommend modifying system_server if you can avoid it.
The system_server process runs as user 1000 (aka system) but other processes can also run as user 1000 simply by specifying that in the AndroidManifest so it doesn't have any special selinux capabilities that other apps cannot have, assuming they are signed with the platform key and run as system.
Create System Application
A platform project can declare itself persistent so Android never kills the process, this may or may not be necessary for your situation.
Android What is use of persistent?
You may not actually need system permissions at all, you could simply have your app installed as a priv-app. Generally you only want to grant your app as much privilege as needed.
What is the difference between system apps and privileged apps on Android?
So finally allow me to suggest an alternative: A persistent content provider.
Assuming your app provides some kind of functionality to unprivileged apps then a content provider that exposes its functionality via the call method is a great choice since you do not need to build an aidl file for it or distribute that aidl to the apps, also apps don't need to bind to your service and you don't have to worry about lifecycle since persistent processes never die.
You can check permissions in the call method to ensure the apps declare themselves. If your process crashes then it doesn't take down the entire system_server with it and when you move to a new version of Android you don't have to figure out how to hack up system_server again.
They are very different. Their high-level differences are:
A Service is an application component that is like an Activity without a UI. You can extend it to create your own version of the Service in your application.
A System Service is part of the System Server. You need to modify AOSP to add your own System Service: provide its API class [MySystem]Manager, its implementation class [MySystem]Service, its AIDL file I[MySystem]Service.aidl, and more. Then you can access it by calling Context.getSystemService(...).
It’s a little confusing to call both of them Service.
Below is the answer to the question, when to use SystemService and when Services
System Services
SystemServices run under SystemServer process
If service is related to any special hardware component and APIs are going to expose
SystemServices has a different Sepolicy and has fewer restrictions as Compared system_app or unknown_app.
Above conditions for you is true then you can Either create SystemService by making changes in AOSP (Normal context.getSystemService(NAME) will work for custom service also) or you can create your own app where you can bind to Servicemanager
Below link for reference
https://devarea.com/aosp-creating-a-system-service/#.YCV3t_nhXDf
Service
it is Non UI component which will run on mainThread.
If requirement scope can be served within APP process context only then this is best place to make changes. Why to bother SystemServer for every small task. :)
In previous versions of Android, I used this method to find if a service from another app was up and running. It worked reliably for me:
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> services = manager.getRunningServices(Integer.MAX_VALUE);
However, with Android O, this is now deprecated and will only return information about the calling app's services. I've looked into other solutions, but I don't want to ask the user for more permissions, (UsageStatsManager, NotificationManager, etc).
Is there an alternate solution for obtaining if a service from a different app is running or not in Android O?
It is intentional that there is no replacement for this function. It is not too clear from the documentation, but from the docs:
Note: this method is only intended for debugging or implementing service management type user interfaces.
Basically, using the method to check other apps services was an unintended side-effect, so Google decided to remove it. Likely for privacy/security purposes to avoid apps "sniffing" other apps/services on the user's device.
You didn't mention your use-case, but you want to avoid asking users for permissions. However, Google is intentionally forcing developers to explicitly request permissions they need, a philosophy which you can find explained here.
As per documentation:
As of O, this method is no longer available to third party applications.
For backwards compatibility, it will still return the caller's own services.
But may be this solution will help: How to check if a service is running on Android?
I've written a library starting a service in the background. It runs perfectly in all applications.
In order to reduce the RAM usage, I want to avoid running multiple services for different applications. Actually, it's pretty enough to use only one service to get things done.
Firstly, I've written an AIDL file to make IPC between applications/libraries. Defined the service as exported/enabled with signature permission. Since all applications are the exactly the same service, it's not possible to check if any one is up or down. While binding the service to check the condition of the service, it always creates and destroys the own service because of the nature of BIND_AUTO_CREATE flag. That's why not possible to get any kind of info from the exported service if it's really up and running.
Then, I tried to define a Content Provider to the manifest of the library. My aim is to share the service info through it. It's really good mechanism to communicate between exported service and application main process. But it is not usable for multiple instances. Because applications which gets the content provider info from the library use the same authority and so it's not possible to install the second one. It gives an DUPLICATE_PROVIDER_AUTHORITY error.
What's your suggestion about the issue? Is there any option to create a master/slave mechanism? Is it possible to make the service singleton for the application uses the library project?
P.S: Tried broadcast and shared preferences techniques. But they're not effective to listen the callback from the exported service.
You need to put the Service in an APK of its own. It needs to have its own unique package name (in the manifest) which is different from the package names of any of the applications that use it. This is how you make the Service behave as a singleton. Now you can use AIDL and bind to the Service in order to have two-way communication.
Note that in more recent versions of Android, it has become necessary to start a Service using an explicit Intent (ie: the Component must be explicitly specified, you can't use just an ACTION).
Alternative 1:
If the use case permits I think you should not implement the Service.
Make your client implement a service a call your library code. This
is how MediaPlayer and other default android APIs work.
Alternative 2:
Host the service in a separate app..and download the app when the
first call is made from any client. From here onwards there will be
single service handling all the client request.This is how some APIs like adobe
air/ MDM solutions from Airwatch works.
There is no good way you can control a component which is running in other app,unless using broadcast receivers and all.
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.
to understand the AIDL in android, i want one real life example, means the at what scenario of development we need to use AIDL.
by reading the Android Docs ... It puts me in confusion and so many question, so it is hard to read whole doc for me, can anyone help me
is it for communicating with outside the phone.
or to communicating with different apps, (why we need to communicate with other apps)
what kind of service they are talking in docs
AIDL is used for Binder. Binder is a mechanism to do RPC calls on/from an Android Service.
When to use AIDL? When you need a Service. When do you need a Service? If you want to share data and control something in another application, you need a service using AIDL as an interface. (A Content Provider is used when sharing data only).
Services can be used within your application as the model roll in the MVC-pattern.
AIDL is Android Interface Definition Language. This basically allows you to do IPC calls.
Use: There are situations where one process would need to talk to other to obtain certain information.
Example: Process A needs info of Call status to determine whether it needs to change Call Type (for example Audio to Video Call or Vice-versa). You may get call status from certain listeners but to change Call type from Audio to Video, Process A needs a hook to change. This "Hook" or way of changing calls is typically part of Telephony Classes which are part of Telephony Process. So in order to obtain such an information from Telephony process, One may write a telephony service (which runs as a part of android telephony process), which will allow you to query or change call type. Since Process A(Client) here is using this remote Service which communicates with Telephony process to alter call type, it needs to have an interface to talk to service. Since Telephony service is the provider, and Process A (client) is the user, they both need to agree on an interface (protocol) they can understand and adhere to. Such an interface is AIDL, which allows you to talk (via a remote service) to Telephony process and get some work done.
Simply put in laymen terms, AIDL is an "agreement" Client gets, which tells it about how to talk to service. Service itself will have a copy of that agreement(since it published for it's clients). Service will then implement details on how it handles once a request arrives or say when someone is talking to it
So process A requests to change call via Service, Service gets the request, it talks to telephony process(since it's part of it) and changes call to video.
An important point to note is, AIDL is only necessary for multithreading environment. You could do away with Binders if you don't need to deal with multithreaded arch.
Another real world example is Google Play License is using AIDL.
I have the same thinking about an example of AIDL, it's very difficult to find an idea to make an example app which uses AIDL. Then I have an idea about it create a LocalLogServerApp. Maybe it can not become a production app but it still shows some value in using AIDL
The main function of this app is
Receive the local log from other local apps (another app need to implement AIDL to send log)
Save the log to datastore
Display the logs
Maybe do something with the local log (eg: search, delete)
Maybe notify developer when error log happened
The benefit of this app
The local log can use when you have some very strange issues which sometimes happened in a few moments and in some specific device. In this case, common Log won't help, debug won't help, Firebase Log may help but Firebase receive log from multiple device.
Reusable, many apps can use it with less code
Hope you find this idea helpful to find another better AIDL example
https://github.com/PhanVanLinh/AndroidLocalLogServer
https://github.com/PhanVanLinh/AndroidLocalLogClientTest
1 - is it for communicating with outside the phone.
Its communicating with outside the app.
2 - or to communicating with different apps, (why we need to communicate with other apps)
As #GodOnScooter mentioned, when your app communicates with telephony service which is actually an other part.
3 - what kind of service they are talking in docs?
This is a service which runs in different process of a system, To bind to this service you need IPC(inter process communication), AIDL is used to implement this.