Permissions for a WearableListenerService - android

I've implemented a WearableListenerService in both my main app and the companion Wear app. In the manifests, the service needs to be declared as android:exported="true" (or not declared at all and left to default to true) since it's started by Google Play Services. An exported service with no permissions can be called by any app on the system, but I can't find the correct permission to add to the service declaration to secure it. I've looked through the permissions on both the phone and the Wear device with pm list permissions but I don't see anything that looks like what I need.
Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?

The best way to see how to implement a WearableListenerService on Android Wear is to look at one of the existing samples provided by the SDK. If you look at the DataLayer sample included at $SDK/samples/android-20/wearable/DataLayer it has a full implementation of what you are wanting to do.
If you look in the AndroidManifest.xml for the wearable side, you can see it has the following:
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<service
android:name=".DataLayerListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
For your security concerns ... When we declare a service in manifest and add a filter to it, it automatically becomes an exported service. So in general, other apps can bind to that service. In case of WearableListenerService, there is a security check that happens in the framework to make sure that the agent binding to that is Google Play Services so no one else can really bind to that service, unless the app developer exposes other intent filters in which case the intention is for others to access it.
So if you implement your code in the same way as the Wear SDK samples, your app should be secure and you do not need to worry about any extra permissions, etc.

Is there a permission that I can/should add to secure my services?
If not, is it a good idea to manually secure the service by checking the package name of the caller?
You don't need to worry about securing your WearableListenerService implementation with permissions or caller package checks. As #Wayne pointed in his answer: there is a security check that happens in the framework. This check is done in the WearableListenerService base class. You can find further security analysis of the Wearable SDK in the following article:
https://labs.mwrinfosecurity.com/blog/android-wear-security-analysis. Here is the quote from it:
The method pr() first checks if com.google.android.gms is Google
signed and then calls cU() to check if the calling process UID is for
the package com.google.android.gms (the Google Play Service package).
If the class is further decompiled, it can be seen that this security
check happens in each method exposed in WearableListenerService.
Unfortunately currently Lint checker produces false positive warning for the wearable listener service declaration whenever it doesn't contain BIND_LISTENER filter (which inclusion produces other warning since it's now deprecated and should be avoided):
Exported services should define a permission that an entity must have in order to launch the service or bind to it. Without this, any application can use this service.
This is certainly a bug in the security detector code (it just wasn't updated when BIND_LISTENER intent became deprecated). I've opened an issue regarding this on the Android bug tracker. Meanwhile to get rid of the warning one needs to add tools:ignore="ExportedService" to its wearable listener service declaration.

Related

What's "AutomaticZenRule" ? What is it used for?

Background
I just noticed some functions of NotificationManager that handle a class that's called AutomaticZenRule :
https://developer.android.com/reference/android/app/NotificationManager.html#addAutomaticZenRule(android.app.AutomaticZenRule)
and others...
The problem
Looking at the docs of AutomaticZenRule, it still doesn't tell much about what it is, and what can it be used for:
Rule instance information for zen mode.
What I tried
Searching the Internet, I can see just in a Commonsware blog post, that they wonder what it is:
It is unclear what AutomaticZenRule is ...
There is practically nothing more that I've found about it. Not "zen mode" and not "AutomaticZenRule".
The questions
What is "zen mode" ?
What is "AutomaticZenRule" , and what can I do with it? How is it related to notifications?
Is there anything special on Android N, that this API was added on this version?
Is there a sample for using it?
Zen Mode is just another name for Do Not Disturb (DND) mode. Android can activate DND mode based on rules. These rules can be provided either by the system, or by a third-party app.
In the following screenshot you can see two system-provided rules, together with a "Driving" rule provided by the third-party app "Pixel Ambient Services":
AutomaticZenRule is there to integrate your own rules into the Android system. To integrate your own rules, you have to follow these rough steps:
Make sure that you have sufficient permissions to access the DND policy (android.permission.ACCESS_NOTIFICATION_POLICY). See NotificationManager.isNotificationPolicyAccessGranted() for details.
Add an activity for your rule:
<activity android:name="MyRuleConfigurationActivity">
<meta-data android:name="android.service.zen.automatic.ruleType" android:value="My Rule" />
<intent-filter>
<action android:name="android.app.action.AUTOMATIC_ZEN_RULE"/>
</intent-filter>
</activity>
Android will show your activity whenever the user wants to create or edit a rule of the specified rule type. In the latter case, Android will supply the ID of the existing rule in NotificationManager#EXTRA_AUTOMATIC_RULE_ID. To propagate changes in your activity back to android, you need to construct an AutomaticZenRuleinstance and call NotificationManager.addAutomaticZenRule / updateAutomaticZenRule.
After that, you can tell Android that the conditions for your rule are currently satisfied / not satisfied by calling NotificationManager.setAutomaticZenRuleState.
From digging in into the other documents available, i was able to understand ZenMode to some extent(although it can be my own version and not the correct one).
What my understanding is as follows -
Zen Mode is the Do not Disturb mode which now in latest updates can be enabled automatically which depends on factors such as late time of the day, etc. AutomaticZenrule can be used by applications who want their notifications to not be masked or suppressed when in do not disturb mode.
For this your application should make request to policy access by sending the user to the activity that matches the system intent action ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS.
If user has granted access to notification policy for your app, then you will be able to set a priority notification even in do not disturb mode. AutomaticZenrule thus plays a vital role to state the system that the application's notifications not be suppressed.
Although, i dont have a running sample code for it, i guess it should be on similar lines like the enabling device admin code or requesting a permission use case.
Thanks to you i got to read something new :)

Security threat by a BroadcastReceiver with GooglePlay's permissions

Does the following situation create a security threat?
Image a situation.
You have a device without GooglePlay services installed.
You create a broadcast receiver with android:permission="com.google.android.c2dm.permission.SEND" permission (this permission is held by GooglePlay services) and install this app on the device.
The app does not check if GooglePlay services are available on the device.
Is it possible for a malicious software to exploit this developer mistake?
It's not very likely that this would cause a problem. There's minimal issue with this because:
This permission is defined by Google for GCM (which has been replaced by FCM.) It is used to ensure that only senders who hold this permission can send that Intent to the registered receivers. It's a small amount of security in the grand scheme of things, though.
Even if a different app / service defined this same permission to fake it on a device where GMS is not present, the normal payload of the Intent is likely going to have some type of extra data in it so Google's receiver (what is specified in your manifest) can verify its content before doing anything with it.
Starting with Android 4.4.3, checks were added to the system so that system bundled apps/services (e.g. GMS) permission definitions take precedence over 3rd party apps. This prevents 3rd party apps from re-defining permissions in an attempt to back-door a system app permission. Not exactly the same situation you describe, but still important.

Answer incoming call using android.telecom and InCallService

Since API 21, Google has been adding features to android.telecom in general, especially by implementing more members of TelecomManager and the addition of InCallService. This last one is is supposed to allow non-system, 3rd-party apps to provide and replace the functionality of the system Calls app in-call screen - the Window that pops up and allows action on EXTRA_STATE_OFFHOOK or EXTRA_STATE_RINGING broadcasts (i.e. incoming and outgoing phone calls).
Currently, only this screen has full control of ringing and active calls and associated system callbacks with fine-grained information, by means of the root-restricted MODIFY_PHONE_STATE permission and a lot of secured AOSP code not even accessible by reflection. It's notably one of the most changed pieces of code in different manufacturers' ROM flavours, together with the launcher, contacts and camera.
This is all very pretty but...
How do you actually develop a 3rd-party InCallService?
Namely:
How do you get notified about, and acquire instances of GSM Calls
How does one answer these calls
What is the life-cycle of the callbacks on this class
Does Google provide any actual tutorial for this that I haven't found
I won't ask answers for all of these at once, but any one answer probably associates to the other questions. This is broad but intrinsically it needs to be: there's no example on the web I've stumbled upon other than AOSP-code, and that code is based on the assumption of root-privileges, which makes it unusable for 3rd-party app development purposes.
How do you get notified about, and acquire instances of GSM Calls
First, the user will need to select your app as the default Phone app. Refer to Replacing default Phone app on Android 6 and 7 with InCallService for a way to do that.
You also need to define an InCallService implementation the system will bind to and notify you about the call:
<service
android:name=".CallService"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
There you should handle at least onCallAdded (set up listeners on Call, start your UI - activity - for the call) and onCallRemoved (remove listeners).
How does one answer these calls
If the user wants to answer the call, you need to invoke the method Call#answer(int) with VideoProfile.STATE_AUDIO_ONLY for example.
What is the life-cycle of the callbacks on this class
Check out Call.Callback for events that can happen with a single call.
Does Google provide any actual tutorial for this that I haven't found
I don't know about Google, but you can check out my simplified example https://github.com/arekolek/simple-phone
Follow the advice from the second comment of Replacing in call app. In addition you need a service that implements the InCallService interface. When a call arrives the onCallAdded(Call call) method will be called, giving you a reference to the call object.
<service
android:name=".InCallServiceImplementation"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
Once you have the call object, answering it's as simple as call.answer(). I suggest that when you get the stuff above working, run a couple of test calls to get to know when the different callbacks are invoked.
Regarding tutorials, I couldn't find any when I was looking into this, but that was over a year ago...
Hope this helps!
I guess Google must've read this question, because apparently on Android 8, a new permission finally allows answering calls through a 3rd party dev-facing permission.
android.permission.ANSWER_PHONE_CALLS (...) allows apps to answer
incoming phone calls programmatically
No details yet though, since the documentation for API 26 hasn't been released yet. I'll make sure to update this answer when they do.
EDIT: user arekolek provided an answer that works perfectly on the original API version of this question (at the time of asking, API was 23, even though the question mentions API 21), thus he gets the tick for right answer. Refer to his answer if you want to implement an incall screen that targets minimum SDK of 23. Note you might need API-dependant code or compat library tweaks if you want it to work on more recent APIs that deprecate (or restrict) usage of the provided sample code. the github repo works as I initially intended.
I would recommend you to see this project to build a dialer app for Android.
https://github.com/HiddenPirates/Dialer

Android multiple services matching intent

In Android, if I send an intent from my app using implicit intent, and there are two services which have a matching intent filter, which service will get invoked ?
I know for activities, the user will be asked a choice through a pop up window. How does Android make the decision in case of services ?
Thanks.
Quoting myself:
In addition, what happens if there are two (or more) services installed on the device that claim to support the same <intent-filter>, but have different package names? You might think that this would fail on install, as happens with providers with duplicate authorities. Alas, it does not. Instead, once again, the first one in “wins”.
So, if we have BadService and GoodService, both responding to the same <intent-filter>, and a client app tries to communicate to GoodService via the explicit Intent matching that <intent-filter>, it might actually be communicating with BadService, simply because BadService was installed first. The user is oblivious to this.
Moral of this story: don't use implicit Intents with services.
They will look to the priority :
<intent-filter android:icon="drawable resource"
android:label="string resource"
android:priority="integer" >
. . .
</intent-filter>
I arrived here because I am using Braze (was appboy) to deliver FCM messages to my app using their AppboyFirebaseMessagingService class. I now need to deliver custom events coming from my backend to my app. At first I thought I should build a new service and add it to the AndroidManifest next to the Braze service. Turns out that won't work as described by #CommonsWare.
What does work is to make a new MyFirebaseMessagingService class that is a subclass of AppboyFirebaseMessagingService and mention the MyFirebaseMessagingService in the AndroidManifest. This way both classes will see all messages. I'll have to add logic to filter for just my messages and ignore the Braze messages.

Prevent service collisions after aapt --rename-manifest-package

I'm creating a white-labeled application. I run the project through aapt with the --rename-manifest-package option.
This allows me write
com.foobar
And release
com.foobar.demo and com.foobar.extended versions to be installed on the same device.
However, even though the services are set via both permission android:permission="#string/permission_name" (which changes per install) and android:exported="false" each app wants to call the other apps services!
I.e. when I start com.foobar.extended I get a security exception about it not having permission for com.foobar.demo's service!
It appears that -rename-manifest-package doesn't change the service intent filters, so they remain com.foobar.services.X meaning that one apps services have higher priority for processing the intents.
How can I prevent this issue? (Maybe a startLocalService() which doesn't send the intents outside the application...)
Thanks,
John
You haven't provided a copy of your manifest file, but I would guess that you have used absolute names there, whereas you should have been using relative names.
Instead of
<service android:name="com.foobar.demo.service" />
you should use
<service android:name=".service" />
(Notice that the name starts with a period).

Categories

Resources