0

Wire up a tracer for Android IP Protection Auth client library

This CL adds the first version of the IP Protection auth client
library and tests the end to end data flow by mocking the auth service.
An Android instrumentation test is added to run the test.
In this initial version, the IPC methods just respond with the same
payload that is passed in the request.

Context:
As part of IP Protection in Android, WebView and Cronet needs to
request for authentication tokens from a system provided
Android service in order to talk to the IP Protection proxy server.
This client library provides a wrapper that handles the IPC to this
authentication service.

Currently, this component is intended to be used by both WebView
and Cronet.

Test: "autoninja -C out/Default ip_protection_auth_test_apk && out/Default/bin/run_ip_protection_auth_test_apk"
Bug: 1467842
Change-Id: I30f3678a0b42b429938d3ad7b0130b4eff6346c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4717487
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Commit-Queue: Abhijith Nair <abhijithnair@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1203188}
This commit is contained in:
Abhijith Nair
2023-09-29 12:00:55 +00:00
committed by Chromium LUCI CQ
parent f2d10cfb2e
commit 3882779f44
19 changed files with 625 additions and 0 deletions
BUILD.gn
components/ip_protection_auth
DIR_METADATAOWNERSREADME.md
client
BUILD.gn
java
src
org
chromium
components
ip_protection_auth
common
javatests
mock_service
BUILD.gn
java
src
org
chromium
components
ip_protection_auth

@ -365,6 +365,7 @@ group("gn_all") {
"//chrome/android/webapk/shell_apk/prepare_upload_dir:prepare_webapk_shell_upload_dir",
"//chrome/test:android_browsertests",
"//components:components_junit_tests",
"//components/ip_protection_auth/javatests:ip_protection_auth_test_apk",
"//content/public/android:content_junit_tests",
"//content/shell/android:content_shell_apk",
"//device:device_junit_tests",

@ -0,0 +1,13 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
team_email: "android-webview-dev@chromium.org"
monorail {
component: "Mobile>WebView"
}
os: ANDROID

@ -0,0 +1,2 @@
abhijithnair@chromium.org
edechamps@google.com

@ -0,0 +1,7 @@
# Android IP Protection Authentication Client Library
As part of IP Protection in Android, Android components like WebView and Cronet
needs to request for authentication tokens from a system provided
Android service in order to talk to the IP Protection proxy server.
This client library provides a wrapper that handles the IPC to this
authentication service.

@ -0,0 +1,18 @@
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
android_library("ip_protection_auth_client_java") {
sources = [ "java/src/org/chromium/components/ip_protection_auth/IpProtectionAuthClient.java" ]
deps = [
"//components/ip_protection_auth/common/aidl:ip_protection_aidl_java",
"//components/ip_protection_auth/common/proto:ip_protection_auth_proto_java",
"//third_party/android_deps:com_google_code_findbugs_jsr305_java",
"//third_party/android_deps:com_google_errorprone_error_prone_annotations_java",
"//third_party/android_deps:protobuf_lite_runtime_java",
"//third_party/androidx:androidx_annotation_annotation_java",
]
}

@ -0,0 +1,214 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.errorprone.annotations.DoNotCall;
import com.google.protobuf.InvalidProtocolBufferException;
import org.chromium.components.ip_protection_auth.common.IIpProtectionAuthAndSignCallback;
import org.chromium.components.ip_protection_auth.common.IIpProtectionAuthService;
import org.chromium.components.ip_protection_auth.common.IIpProtectionGetInitialDataCallback;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignResponse;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataResponse;
/**
* Client interface for the IP Protection Auth service.
*
* The methods in this class are thread-safe (except for close() which should not be called
* concurrently with other methods).
*
* TODO(abhijithnair): Update documentation once production ready.
* DO NOT DEPEND. CURRENTLY UNDER DEVELOPMENT.
*/
public final class IpProtectionAuthClient implements AutoCloseable {
// Only used for testing.
private static final String IP_PROTECTION_AUTH_STUB_SERVICE_NAME =
"org.chromium.components.ip_protection_auth.mock_service.IpProtectionAuthServiceMock";
// mService being null signifies that the object has been closed by calling close().
@Nullable
private IIpProtectionAuthService mService;
// We need to store this to unbind from the service.
@Nullable
private ConnectionSetup mConnection;
private static final class ConnectionSetup implements ServiceConnection {
private final IpProtectionAuthServiceCallback mCallback;
private final Context mContext;
ConnectionSetup(
@NonNull Context context, @NonNull IpProtectionAuthServiceCallback callback) {
mContext = context;
mCallback = callback;
}
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
IpProtectionAuthClient ipProtectionClient = new IpProtectionAuthClient(
this, IIpProtectionAuthService.Stub.asInterface(iBinder));
mCallback.onResult(ipProtectionClient);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mContext.unbindService(this);
}
@Override
public void onBindingDied(ComponentName name) {
mContext.unbindService(this);
}
@Override
public void onNullBinding(ComponentName name) {
mContext.unbindService(this);
}
}
private static final class IIpProtectionGetInitialDataCallbackStub
extends IIpProtectionGetInitialDataCallback.Stub {
private final GetInitialDataCallback mCallback;
IIpProtectionGetInitialDataCallbackStub(GetInitialDataCallback callback) {
mCallback = callback;
}
@Override
public void reportResult(byte[] bytes) {
try {
mCallback.onResult(GetInitialDataResponse.parser().parseFrom(bytes));
} catch (InvalidProtocolBufferException ex) {
// TODO(abhijithnair): Handle this case correctly.
throw new RuntimeException(ex);
}
}
@Override
public void reportError(byte[] bytes) {
mCallback.onError(bytes);
}
}
private static final class IIpProtectionAuthAndSignCallbackStub
extends IIpProtectionAuthAndSignCallback.Stub {
private final AuthAndSignCallback mCallback;
IIpProtectionAuthAndSignCallbackStub(AuthAndSignCallback callback) {
mCallback = callback;
}
@Override
public void reportResult(byte[] bytes) {
try {
mCallback.onResult(AuthAndSignResponse.parser().parseFrom(bytes));
} catch (InvalidProtocolBufferException ex) {
// TODO(abhijithnair): Handle this case correctly.
throw new RuntimeException(ex);
}
}
@Override
public void reportError(byte[] bytes) {
mCallback.onError(bytes);
}
}
public interface IpProtectionAuthServiceCallback {
void onResult(IpProtectionAuthClient client);
void onError(String error);
}
public interface GetInitialDataCallback {
// TODO(abhijithnair): Consider using a non-proto generated class.
void onResult(GetInitialDataResponse result);
// TODO(abhijithnair): Change to using a error specific class.
void onError(byte[] error);
}
public interface AuthAndSignCallback {
// TODO(abhijithnair): Consider using a non-proto generated class.
void onResult(AuthAndSignResponse result);
// TODO(abhijithnair): Change to using a error specific class.
void onError(byte[] error);
}
IpProtectionAuthClient(@NonNull ConnectionSetup connectionSetup,
@NonNull IIpProtectionAuthService ipProtectionAuthService) {
mConnection = connectionSetup;
mService = ipProtectionAuthService;
}
@VisibleForTesting
public static void createConnectedInstanceForTestingAsync(
@NonNull Context context, @NonNull IpProtectionAuthServiceCallback callback) {
ComponentName componentName =
new ComponentName(context, IP_PROTECTION_AUTH_STUB_SERVICE_NAME);
Intent intent = new Intent();
intent.setComponent(componentName);
ConnectionSetup connectionSetup = new ConnectionSetup(context, callback);
context.bindService(intent, connectionSetup, Context.BIND_AUTO_CREATE);
}
@DoNotCall
public static void createConnectedInstance(
@NonNull Context context, @NonNull IpProtectionAuthServiceCallback callback) {
// TODO(abhijithnair): Implement!
throw new UnsupportedOperationException("unimplemented");
}
public void getInitialData(GetInitialDataRequest request, GetInitialDataCallback callback) {
if (mService == null) {
// This denotes a coding error by the caller so it makes sense to throw an unchecked
// exception.
throw new IllegalStateException("Already closed");
}
IIpProtectionGetInitialDataCallbackStub callbackStub =
new IIpProtectionGetInitialDataCallbackStub(callback);
try {
mService.getInitialData(request.toByteArray(), callbackStub);
} catch (RemoteException ex) {
// TODO(abhijithnair): Handle this case correctly.
}
}
public void authAndSign(AuthAndSignRequest request, AuthAndSignCallback callback) {
if (mService == null) {
// This denotes a coding error by the caller so it makes sense to throw an unchecked
// exception.
throw new IllegalStateException("Already closed");
}
IIpProtectionAuthAndSignCallbackStub callbackStub =
new IIpProtectionAuthAndSignCallbackStub(callback);
try {
mService.authAndSign(request.toByteArray(), callbackStub);
} catch (RemoteException ex) {
// TODO(abhijithnair): Handle this case correctly.
}
}
@Override
public void close() {
mConnection.mContext.unbindService(mConnection);
mConnection = null;
mService = null;
}
}

@ -0,0 +1,19 @@
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
import("//testing/test.gni")
android_aidl("ip_protection_aidl") {
import_include = [ "src" ]
sources = [
"src/org/chromium/components/ip_protection_auth/common/IIpProtectionAuthAndSignCallback.aidl",
"src/org/chromium/components/ip_protection_auth/common/IIpProtectionAuthService.aidl",
"src/org/chromium/components/ip_protection_auth/common/IIpProtectionGetInitialDataCallback.aidl",
]
}
android_library("ip_protection_aidl_java") {
srcjar_deps = [ ":ip_protection_aidl" ]
}

@ -0,0 +1,15 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth.common;
/**
* Used for communicating the result of authAndSign() to the caller.
*/
oneway interface IIpProtectionAuthAndSignCallback {
// Parameter is the serialized form of AuthAndSignResponse proto
void reportResult(in byte[] response) = 0;
// Parameter is the serialized form of AuthAndSignError proto
void reportError(in byte[] error) = 1;
}

@ -0,0 +1,18 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth.common;
import org.chromium.components.ip_protection_auth.common.IIpProtectionAuthAndSignCallback;
import org.chromium.components.ip_protection_auth.common.IIpProtectionGetInitialDataCallback;
/**
* Used for conversing with the IP Protection Service.
*/
interface IIpProtectionAuthService {
// Request should be the serialized form of GetInitialDataRequest proto
void getInitialData(in byte[] request, in IIpProtectionGetInitialDataCallback callback) = 0;
// Request should be the serialized form of AuthAndSignRequest proto
void authAndSign(in byte[] request, in IIpProtectionAuthAndSignCallback callback) = 1;
}

@ -0,0 +1,15 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth.common;
/**
* Used for communicating the result of getInitialData() to the caller.
*/
oneway interface IIpProtectionGetInitialDataCallback {
// Parameter is the serialized form of GetInitialDataResponse proto
void reportResult(in byte[] response) = 0;
// Parameter is the serialized form of GetInitialDataError proto
void reportError(in byte[] error) = 1;
}

@ -0,0 +1,2 @@
per-file *.aidl=set noparent
per-file *.aidl=file://ipc/SECURITY_OWNERS

@ -0,0 +1,11 @@
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
import("//third_party/protobuf/proto_library.gni")
proto_java_library("ip_protection_auth_proto_java") {
proto_path = "."
sources = [ "ip_protection_auth.proto" ]
}

@ -0,0 +1,38 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
syntax = "proto3";
package org.chromium.components.ip_protection_auth.common.proto;
option optimize_for = LITE_RUNTIME; // TODO(crbug/800281): Remove this after proto 4.0
option java_package = "org.chromium.components.ip_protection_auth.common.proto";
option java_outer_classname = "IpProtectionAuthProtos";
// TODO(abhijithnair): Currently this is a sample used to get the end to end
// data flow set up. This will be modified with real fields.
// Next tag: 2
message GetInitialDataRequest {
string test_payload = 1;
}
// TODO(abhijithnair): Currently this is a sample used to get the end to end
// data flow set up. This will be modified with real fields.
// Next tag: 2
message GetInitialDataResponse {
string test_payload = 1;
}
// TODO(abhijithnair): Currently this is a sample used to get the end to end
// data flow set up. This will be modified with real fields.
// Next tag: 2
message AuthAndSignRequest {
string test_payload = 1;
}
// TODO(abhijithnair): Currently this is a sample used to get the end to end
// data flow set up. This will be modified with real fields.
// Next tag: 2
message AuthAndSignResponse {
string test_payload = 1;
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 The Chromium Authors
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.components.ip_protection_auth">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:label="Ip Protection Auth">
<service android:name="org.chromium.components.ip_protection_auth.mock_service.IpProtectionAuthServiceMock"
android:exported="true" />
</application>
</manifest>

@ -0,0 +1,30 @@
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
import("//testing/test.gni")
instrumentation_test_apk("ip_protection_auth_test_apk") {
apk_name = "IpProtectionAuthTest"
apk_under_test = ":ip_protection_auth_apk"
android_manifest = "InstrumentationTestAndroidManifest.xml"
sources = [ "src/org/chromium/components/ip_protection_auth/test/IpProtectionAuthTest.java" ]
deps = [
"../client:ip_protection_auth_client_java",
"//base:base_java_test_support",
"//components/ip_protection_auth/common/proto:ip_protection_auth_proto_java",
"//third_party/android_deps:protobuf_lite_runtime_java",
"//third_party/androidx:androidx_test_core_java",
"//third_party/androidx:androidx_test_ext_junit_java",
"//third_party/androidx:androidx_test_runner_java",
"//third_party/google-truth:google_truth_java",
"//third_party/junit:junit",
]
}
android_apk("ip_protection_auth_apk") {
apk_name = "IpProtectionAuth"
android_manifest = "AndroidManifest.xml"
deps = [ "../mock_service:ip_protection_auth_service_mock_java" ]
}

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 The Chromium Authors
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.components.ip_protection_auth.test">
<instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner"
android:targetPackage="org.chromium.components.ip_protection_auth"
android:label="Tests for org.chromium.chromium.components.ip_protection_auth"/>
<uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
</manifest>

@ -0,0 +1,112 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth.test;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.content.Context;
import android.os.ConditionVariable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.Batch;
import org.chromium.components.ip_protection_auth.IpProtectionAuthClient;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignResponse;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataResponse;
@MediumTest
@RunWith(AndroidJUnit4.class)
@Batch(Batch.UNIT_TESTS)
public final class IpProtectionAuthTest {
IpProtectionAuthClient mIpProtectionClient;
@Before
public void setUp() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
final ConditionVariable conditionVariable = new ConditionVariable();
IpProtectionAuthClient.IpProtectionAuthServiceCallback callback =
new IpProtectionAuthClient.IpProtectionAuthServiceCallback() {
@Override
public void onResult(IpProtectionAuthClient client) {
mIpProtectionClient = client;
conditionVariable.open();
}
@Override
public void onError(String error) {
fail("onError should not be called");
}
};
IpProtectionAuthClient.createConnectedInstanceForTestingAsync(context, callback);
assertThat(conditionVariable.block(5000)).isTrue();
}
@After
public void tearDown() {
mIpProtectionClient.close();
}
@Test
public void getInitialDataTest() throws Exception {
final ConditionVariable conditionVariable = new ConditionVariable();
// Using a 1-element array so that the reference is final and can be passed into the lambda.
final GetInitialDataResponse[] getInitialDataResponse = new GetInitialDataResponse[1];
IpProtectionAuthClient.GetInitialDataCallback getInitialDataCallback =
new IpProtectionAuthClient.GetInitialDataCallback() {
@Override
public void onResult(GetInitialDataResponse response) {
getInitialDataResponse[0] = response;
conditionVariable.open();
}
@Override
public void onError(byte[] error) {
fail("onError should not be called");
}
};
GetInitialDataRequest request =
GetInitialDataRequest.newBuilder().setTestPayload("get initial data").build();
mIpProtectionClient.getInitialData(request, getInitialDataCallback);
assertThat(conditionVariable.block(5000)).isTrue();
assertThat(getInitialDataResponse[0].getTestPayload()).isEqualTo("get initial data");
}
@Test
public void authAndSignTest() throws Exception {
final ConditionVariable conditionVariable = new ConditionVariable();
// Using a 1-element array so that the reference is final and can be passed into the lambda.
final AuthAndSignResponse[] authAndSignResponse = new AuthAndSignResponse[1];
IpProtectionAuthClient.AuthAndSignCallback authAndSignCallback =
new IpProtectionAuthClient.AuthAndSignCallback() {
@Override
public void onResult(AuthAndSignResponse response) {
authAndSignResponse[0] = response;
conditionVariable.open();
}
@Override
public void onError(byte[] bytes) {
fail("onError should not be called");
}
};
AuthAndSignRequest authAndSignRequest =
AuthAndSignRequest.newBuilder().setTestPayload("auth and sign").build();
mIpProtectionClient.authAndSign(authAndSignRequest, authAndSignCallback);
assertThat(conditionVariable.block(5000)).isTrue();
assertThat(authAndSignResponse[0].getTestPayload()).isEqualTo("auth and sign");
}
}

@ -0,0 +1,13 @@
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
android_library("ip_protection_auth_service_mock_java") {
sources = [ "java/src/org/chromium/components/ip_protection_auth/mock_service/IpProtectionAuthServiceMock.java" ]
deps = [
"//components/ip_protection_auth/common/aidl:ip_protection_aidl_java",
"//components/ip_protection_auth/common/proto:ip_protection_auth_proto_java",
"//third_party/android_deps:protobuf_lite_runtime_java",
"//third_party/androidx:androidx_annotation_annotation_java",
]
}

@ -0,0 +1,74 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.ip_protection_auth.mock_service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import com.google.protobuf.InvalidProtocolBufferException;
import org.chromium.components.ip_protection_auth.common.IIpProtectionAuthAndSignCallback;
import org.chromium.components.ip_protection_auth.common.IIpProtectionAuthService;
import org.chromium.components.ip_protection_auth.common.IIpProtectionGetInitialDataCallback;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.AuthAndSignResponse;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataRequest;
import org.chromium.components.ip_protection_auth.common.proto.IpProtectionAuthProtos.GetInitialDataResponse;
/**
* Mock implementation of the IP Protection Auth Service
*/
public final class IpProtectionAuthServiceMock extends Service {
private static final String TAG = "IpProtectionAuthServiceMock";
private final IIpProtectionAuthService.Stub mBinder = new IIpProtectionAuthService.Stub() {
// TODO(abhijithnair): Currently this method just passes the same request byte[] back as the
// result. Use a mock result instead.
@Override
public void getInitialData(byte[] bytes, IIpProtectionGetInitialDataCallback callback) {
try {
GetInitialDataRequest request = GetInitialDataRequest.parser().parseFrom(bytes);
GetInitialDataResponse response = GetInitialDataResponse.newBuilder()
.setTestPayload(request.getTestPayload())
.build();
callback.reportResult(response.toByteArray());
} catch (RemoteException ex) {
// TODO(abhijithnair): Handle this exception correctly.
throw new RuntimeException(ex);
} catch (InvalidProtocolBufferException ex) {
// TODO(abhijithnair): Handle this exception correctly.
throw new RuntimeException(ex);
}
}
// TODO(abhijithnair): Currently this method just passes the same request byte[] back as the
// result. Use a mock result instead.
@Override
public void authAndSign(byte[] bytes, IIpProtectionAuthAndSignCallback callback) {
try {
AuthAndSignRequest request = AuthAndSignRequest.parser().parseFrom(bytes);
AuthAndSignResponse response = AuthAndSignResponse.newBuilder()
.setTestPayload(request.getTestPayload())
.build();
callback.reportResult(response.toByteArray());
} catch (RemoteException ex) {
// TODO(abhijithnair): Handle this exception correctly.
throw new RuntimeException(ex);
} catch (InvalidProtocolBufferException ex) {
// TODO(abhijithnair): Handle this exception correctly.
throw new RuntimeException(ex);
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}