public void verify(PublicKey publicKey, int responseCode, String signedData, String signature) {
        String userId = null;
        // Skip signature check for unsuccessful requests
        ResponseData data = null;
        if (responseCode == LICENSED || responseCode == NOT_LICENSED ||
                responseCode == LICENSED_OLD_KEY) {
            // Verify signature.
            try {
                if (TextUtils.isEmpty(signedData)) {
                    XLog.e(TAG, "Signature verification failed: signedData is empty. " +
                            "(Device not signed-in to any Google accounts?)");
                    handleInvalidResponse();
                    return;
                }

                Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
                sig.initVerify(publicKey);
                sig.update(signedData.getBytes());

                if (!sig.verify(Base64.decode(signature))) {
                    XLog.e(TAG, "Signature verification failed.");
                    handleInvalidResponse();
                    return;
                }
            } catch (NoSuchAlgorithmException e) {
                // This can't happen on an Android compatible device.
                throw new RuntimeException(e);
            } catch (InvalidKeyException e) {
                handleApplicationError(LicenseCheckerCallback.ERROR_INVALID_PUBLIC_KEY);
                return;
            } catch (SignatureException e) {
                throw new RuntimeException(e);
            } catch (Base64DecoderException e) {
                XLog.e(TAG, "Could not Base64-decode signature.");
                handleInvalidResponse();
                return;
            }

            // Parse and validate response.
            try {
                data = ResponseData.parse(signedData);
            } catch (IllegalArgumentException e) {
                XLog.e(TAG, "Could not parse response.");
                handleInvalidResponse();
                return;
            }

            if (data.responseCode != responseCode) {
                XLog.e(TAG, "Response codes don't match.");
                handleInvalidResponse();
                return;
            }

            if (data.nonce != mNonce) {
                XLog.e(TAG, "Nonce doesn't match.");
                handleInvalidResponse();
                return;
            }

            if (!data.packageName.equals(mPackageName)) {
                XLog.e(TAG, "Package name doesn't match.");
                handleInvalidResponse();
                return;
            }

            if (!data.versionCode.equals(mVersionCode)) {
                XLog.e(TAG, "Version codes don't match.");
                handleInvalidResponse();
                return;
            }

            // Application-specific user identifier.
            userId = data.userId;
            if (TextUtils.isEmpty(userId)) {
                XLog.e(TAG, "User identifier is empty.");
                handleInvalidResponse();
                return;
            }
        }

        switch (responseCode) {
            case LICENSED:
            case LICENSED_OLD_KEY:
                int limiterResponse = mDeviceLimiter.isDeviceAllowed(userId);
                handleResponse(limiterResponse, data);
                break;
            case NOT_LICENSED:
                handleResponse(Policy.NOT_LICENSED, data);
                break;
            case ERROR_CONTACTING_SERVER:
                XLog.w(TAG, "Error contacting licensing server.");
                handleResponse(Policy.RETRY, data);
                break;
            case ERROR_SERVER_FAILURE:
                XLog.w(TAG, "An error has occurred on the licensing server.");
                handleResponse(Policy.RETRY, data);
                break;
            case ERROR_OVER_QUOTA:
                XLog.w(TAG, "Licensing server is refusing to talk to this device, over quota.");
                handleResponse(Policy.RETRY, data);
                break;
            case ERROR_INVALID_PACKAGE_NAME:
                handleApplicationError(LicenseCheckerCallback.ERROR_INVALID_PACKAGE_NAME);
                break;
            case ERROR_NON_MATCHING_UID:
                handleApplicationError(LicenseCheckerCallback.ERROR_NON_MATCHING_UID);
                break;
            case ERROR_NOT_MARKET_MANAGED:
                handleApplicationError(LicenseCheckerCallback.ERROR_NOT_MARKET_MANAGED);
                break;
            default:
                XLog.e(TAG, "Unknown response code for license check.");
                handleInvalidResponse();
        }
    }
Verifies the response from server and calls appropriate callback method.

@param publicKey    public key associated with the developer account
@param responseCode server response code
@param signedData   signed data from server
@param signature    server signature
android/android_framework/base/src/main/java/com/google/android/vending/licensing/LicenseValidator.java