CarEnrolmentActivity.java revision 77e5e49cf9dcceb69b07510c380ae2a9285ebfee
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16package com.android.car.trust;
17
18import android.app.Activity;
19import android.bluetooth.BluetoothDevice;
20import android.content.BroadcastReceiver;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.content.ServiceConnection;
26import android.content.SharedPreferences;
27import android.os.Bundle;
28import android.os.IBinder;
29import android.os.RemoteException;
30import android.preference.PreferenceManager;
31import android.support.v4.content.LocalBroadcastManager;
32import android.util.Log;
33import android.view.View;
34import android.widget.Button;
35import android.widget.TextView;
36import com.android.car.trust.CarEnrolmentService.EnrolmentCallback;
37import com.android.car.trust.comms.SimpleBleServer.ConnectionListener;
38
39import static com.android.car.trust.CarBleTrustAgent.ACTION_ADD_TOKEN_RESULT;
40import static com.android.car.trust.CarBleTrustAgent.ACTION_TOKEN_STATUS_RESULT;
41import static com.android.car.trust.CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE;
42import static com.android.car.trust.CarBleTrustAgent.INTENT_EXTRA_TOKEN_STATUS;
43
44/**
45 * Setup activity that binds {@link CarEnrolmentService} and starts the enrolment process.
46 */
47public class CarEnrolmentActivity extends Activity {
48    private static String TAG = "CarEnrolment";
49    private static String SP_HANDLE_KEY = "sp-test";
50
51    private TextView mOutputText;
52    private TextView mStartButton;
53
54    private long mHandle;
55
56    private CarEnrolmentService mEnrolmentService;
57
58    private BluetoothDevice mDevice;
59
60    private boolean mServiceBound;
61
62    private LocalBroadcastManager mLocalBroadcastManager;
63
64    private SharedPreferences mPrefs;
65
66    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
67        @Override
68        public void onReceive(Context context, Intent intent) {
69            intent.getPackage();
70
71            String action = intent.getAction();
72            Log.d(TAG, "Received broadcast: " + action);
73            if (ACTION_TOKEN_STATUS_RESULT.equals(action)) {
74                boolean tokenActive = intent.getBooleanExtra(INTENT_EXTRA_TOKEN_STATUS, false);
75                appendOutputText("Is token active? " + tokenActive + " handle: " + mHandle);
76            } else if (ACTION_ADD_TOKEN_RESULT.equals(action)) {
77                final long handle = intent.getLongExtra(INTENT_EXTRA_TOKEN_HANDLE, -1);
78
79                runOnUiThread(new Runnable() {
80                    @Override
81                    public void run() {
82                        Log.d(TAG, "about to store new handle");
83                        mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply();
84                        Log.d(TAG, "stored new handle");
85                    }
86                });
87
88                mEnrolmentService.sendHandle(handle, mDevice);
89                appendOutputText("Escrow Token Added. Handle: " + handle
90                        + "\nLock and unlock the device to activate token");
91            }
92        }
93    };
94
95    @Override
96    protected void onCreate(Bundle savedInstanceState) {
97        super.onCreate(savedInstanceState);
98
99        setContentView(R.layout.car_client);
100        mOutputText = (TextView) findViewById(R.id.textfield);
101
102        final Intent intent = new Intent(this, CarEnrolmentService.class);
103
104        mPrefs = PreferenceManager.getDefaultSharedPreferences(this /* context */);
105
106        IntentFilter filter = new IntentFilter();
107        filter.addAction(ACTION_TOKEN_STATUS_RESULT);
108        filter.addAction(ACTION_ADD_TOKEN_RESULT);
109
110        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this /* context */);
111        mLocalBroadcastManager.registerReceiver(mReceiver, filter);
112
113        mStartButton = (Button) findViewById(R.id.start_button);
114        mStartButton.setOnClickListener(new View.OnClickListener() {
115            @Override
116            public void onClick(View v) {
117                // binding the service will start it if not started.
118                bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
119            }
120        });
121
122        Button revokeButton = (Button) findViewById(R.id.revoke_trust_button);
123        revokeButton.setOnClickListener(new View.OnClickListener() {
124            @Override
125            public void onClick(View v) {
126                Intent intent = new Intent(CarBleTrustAgent.ACTION_REVOKE_TRUST);
127                intent.setPackage(getPackageName());
128                sendBroadcast(intent);
129            }
130        });
131    }
132
133    private ServiceConnection mServiceConnection = new ServiceConnection() {
134        public void onServiceConnected(ComponentName className,
135                IBinder service) {
136            mServiceBound = true;
137            CarEnrolmentService.EnrolmentServiceBinder binder
138                    = (CarEnrolmentService.EnrolmentServiceBinder) service;
139            mEnrolmentService = binder.getService();
140            mEnrolmentService.addEnrolmentCallback(mEnrolmentCallback);
141            mEnrolmentService.addConnectionListener(mConnectionListener);
142            mEnrolmentService.start();
143        }
144
145        public void onServiceDisconnected(ComponentName arg0) {
146            mEnrolmentService = null;
147            mServiceBound = false;
148        }
149    };
150
151    @Override
152    public void onResume() {
153        super.onResume();
154
155        if (!mPrefs.contains(SP_HANDLE_KEY)) {
156            appendOutputText("No handles found.");
157            return;
158        }
159
160        try {
161            mHandle = mPrefs.getLong(SP_HANDLE_KEY, -1);
162            Log.d(TAG, "onResume, checking handle active: " + mHandle);
163            isTokenActive(mHandle);
164        } catch (RemoteException e) {
165            Log.e(TAG, "Error checking if token is valid");
166            appendOutputText("Error checking if token is valid");
167        }
168    }
169
170    @Override
171    public void onDestroy() {
172        if (mServiceBound) {
173            unbindService(mServiceConnection);
174        }
175        super.onDestroy();
176    }
177
178    private void appendOutputText(final String text) {
179        runOnUiThread(new Runnable() {
180            @Override
181            public void run() {
182                mOutputText.append("\n" + text);
183            }
184        });
185    }
186
187    private ConnectionListener mConnectionListener = new ConnectionListener() {
188        @Override
189        public void onServerStarted() {
190            appendOutputText("Server started");
191        }
192
193        @Override
194        public void onServerStartFailed(int errorCode) {
195            appendOutputText("Server failed to start, error code: " + errorCode);
196        }
197
198        @Override
199        public void onDeviceConnected(BluetoothDevice device) {
200            mDevice = device;
201            appendOutputText("Device connected: " + device.getName()
202                    + " addr: " + device.getAddress());
203        }
204    };
205
206    private EnrolmentCallback mEnrolmentCallback = new EnrolmentCallback() {
207        @Override
208        public void onEnrolmentDataReceived(byte[] token) {
209            appendOutputText("Enrolment data received ");
210            addEscrowToken(token);
211        }
212    };
213
214    private void isTokenActive(long handle) throws RemoteException {
215        Intent intent = new Intent();
216        intent.setAction(CarBleTrustAgent.ACTION_IS_TOKEN_ACTIVE);
217        intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE, handle);
218
219        mLocalBroadcastManager.sendBroadcast(intent);
220    }
221
222    private void addEscrowToken(byte[] token) {
223        long handle;
224
225        if (mPrefs.contains(SP_HANDLE_KEY)) {
226            handle = mPrefs.getLong(SP_HANDLE_KEY, -1);
227            appendOutputText("Removing old token, handle value: " + handle);
228            Intent intent = new Intent();
229            intent.setAction(CarBleTrustAgent.ACTION_REMOVE_TOKEN);
230            intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE, handle);
231            mLocalBroadcastManager.sendBroadcast(intent);
232        }
233
234        Intent intent = new Intent();
235        intent.setAction(CarBleTrustAgent.ACTION_ADD_TOKEN);
236        intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_ESCROW_TOKEN, token);
237
238        mLocalBroadcastManager.sendBroadcast(intent);
239    }
240}
241