microg/GmsCore · error · SecurityException
Caller is not Services Core
Error message
Caller is not Services Core
What it means
WearableListenerService.onBind/onStartCommand (post) validates that the calling UID belongs to Google Play services (GMS package) before dispatching wearable events. If the caller's packages, looked up via getPackagesForUid, do not include GMS_PACKAGE_NAME, a SecurityException is thrown. This protects the listener from spoofed Intents sent by other apps.
Source
Thrown at play-services-wearable/src/main/java/com/google/android/gms/wearable/WearableListenerService.java:145
}
@Override
public void onPeerDisconnected(Node peer) {
}
private class Listener extends IWearableListener.Stub {
private int knownGoodUid = -1;
private boolean post(Runnable runnable) {
int callingUid = Binder.getCallingUid();
if (callingUid != knownGoodUid) {
// TODO: Verify Gms is calling
String[] packagesForUid = getPackageManager().getPackagesForUid(callingUid);
if (packagesForUid != null) {
if (Arrays.asList(packagesForUid).contains(GMS_PACKAGE_NAME)) {
knownGoodUid = callingUid;
} else {
throw new SecurityException("Caller is not Services Core");
}
}
}
synchronized (lock) {
if (disconnected) {
return false;
}
serviceHandler.post(runnable);
return true;
}
}
@Override
public void onDataChanged(final DataHolder data) throws RemoteException {
post(new Runnable() {
@Override
public void run() {
WearableListenerService.this.onDataChanged(new DataEventBuffer(data));View on GitHub (pinned to 157c9d86ac)
Solutions
- Ensure wearable events come only from the platform/Play services routing (use the Wearable DataClient/MessageClient APIs instead of manual Intents).
- On custom ROMs, install a properly signed GmsCore (e.g. microG signed variant) so the caller UID maps to the GMS package.
- In tests, mock the wearable clients rather than delivering Intents directly to WearableListenerService.
- Check getPackagesForUid(callingUid) in a debugging session to identify which package actually sent the Intent.
Example fix
// before
context.startService(new Intent(context, MyListenerService.class)
.setAction(DataMapListenerIntentAction));
// after
Wearable.getDataClient(context).addListener(myListener); // let Play services deliver events Defensive patterns
Strategy: try-catch
Validate before calling
String[] pkgs = getPackageManager().getPackagesForUid(callingUid);
boolean fromGms = pkgs != null && Arrays.asList(pkgs).contains("com.google.android.gms"); Try / catch
try {
listenerService.onMessageReceived(event);
} catch (SecurityException e) {
Log.w(TAG, "Untrusted wearable event caller", e);
} Prevention
- Only send wearable data via Wearable API clients
- Do not spoof listener Intents in tests; use mocks
- Verify GmsCore signing on modified ROMs
When it happens
Trigger: Another app (or a test harness) sends an explicit Intent to WearableListenerService (action com.google.android.gms.wearable.DATA_CHANGED etc.) with a UID not owned by Google Play services; the service handles it via onDataChanged/onMessageReceived/onPeerConnected/onPeerDisconnected/onConnectedNodes/onConnectedCapabilityChanged and post() throws.
Common situations: Developers manually broadcasting fake wearable Intents to test the listener; running the app on a device without a properly installed/signed Play Services package; custom ROMs with unsigned GmsCore; instrumentation tests binding to the service directly.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Access denied, missing google package permission for
- suggested UID [
- suggested PID [
- UID [
- Access denied, missing google package permission or GET_ACCO
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/4a8e1275d1a7a50a.
Report an issue: GitHub.