microg/GmsCore · error · UnsupportedOperationException

Op code ${request.opCode} not supported

Error message

Op code ${request.opCode} not supported

What it means

LocationManagerInstance.updateDeviceOrientationRequest dispatches only REQUEST_UPDATES and REMOVE_UPDATES op codes; any other op code throws UnsupportedOperationException('Op code X not supported'). The exception message is forwarded to the FusedLocationProviderCallback as a failed FusedLocationProviderResult rather than crashing the caller. It guards against malformed or newer-protocol requests reaching the device-orientation handler.

Source

Thrown at play-services-location/core/src/main/kotlin/org/microg/gms/location/manager/LocationManagerInstance.kt:390

    }

    // endregion

    // endregion

    // region Device Orientation

    override fun updateDeviceOrientationRequest(request: DeviceOrientationRequestUpdateData) {
        Log.d(TAG, "updateDeviceOrientationRequest by ${getClientIdentity().packageName}")
        checkHasAnyLocationPermission()
        val clientIdentity = getClientIdentity()
        val callback = request.fusedLocationProviderCallback
        lifecycleScope.launchWhenStarted {
            try {
                when (request.opCode) {
                    REQUEST_UPDATES -> locationManager.deviceOrientationManager.add(clientIdentity, request.request, request.listener)
                    REMOVE_UPDATES -> locationManager.deviceOrientationManager.remove(clientIdentity, request.listener)
                    else -> throw UnsupportedOperationException("Op code ${request.opCode} not supported")
                }
                callback?.onFusedLocationProviderResult(FusedLocationProviderResult.SUCCESS)
            } catch (e: Exception) {
                try {
                    callback?.onFusedLocationProviderResult(FusedLocationProviderResult.create(Status(CommonStatusCodes.ERROR, e.message)))
                } catch (e2: Exception) {
                    Log.w(TAG, "Failed", e)
                }
            }
        }
    }

    // endregion

    private fun getClientIdentity() = ClientIdentity(packageName).apply { uid = getCallingUid(); pid = getCallingPid() }

    private fun checkHasAnyLocationPermission() = checkHasAnyPermission(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION)

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Only invoke the supported operations: request updates or remove updates via the DeviceOrientationClient.
  2. Check the operation/status result delivered to the callback and handle Status with code CommonStatusCodes.ERROR gracefully.
  3. Update microG to a version supporting the op code, or pin the app to an older play-services-location client version whose op codes are implemented.

Example fix

// before
deviceOrientationClient.requestDeviceOrientationUpdates(request, callback) // opCode=UNKNOWN from newer client
// after
// use only supported ops
deviceOrientationClient.requestDeviceOrientationUpdates(orientationRequest, listener) // REQUEST_UPDATES
deviceOrientationClient.removeDeviceOrientationUpdates(listener) // REMOVE_UPDATES
Defensive patterns

Strategy: try-catch

Type guard

fun isSupportedOrientationOpCode(opCode: Int) = opCode == REQUEST_UPDATES || opCode == REMOVE_UPDATES

Try / catch

deviceOrientationClient.requestDeviceOrientationUpdates(req, listener) // result arrives via callback
// in callback:
override fun onFusedLocationProviderResult(result: FusedLocationProviderResult) {
    if (!result.status.isSuccess && result.status.message?.contains("not supported") == true) {
        // fall back to plain location updates
    }
}

Prevention

When it happens

Trigger: Sending a RequestDeviceOrientationRequest whose opCode is neither REQUEST_UPDATES nor REMOVE_UPDATES — e.g. a client compiled against a newer play-services API that added an op code microG does not implement, or a corrupted/ hand-crafted request.

Common situations: Running a new Google Play services client library (which introduced additional device-orientation op codes) against microG, which only implements the original two; tests passing sentinel op codes.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/d133d4af54680984. Report an issue: GitHub.