Home | History | Annotate | Download | only in trust
      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  */
     16 package com.android.car.trust;
     17 
     18 import android.Manifest;
     19 import android.app.Activity;
     20 import android.bluetooth.BluetoothDevice;
     21 import android.car.trust.ICarTrustAgentBleCallback;
     22 import android.car.trust.ICarTrustAgentBleService;
     23 import android.car.trust.ICarTrustAgentEnrolmentCallback;
     24 import android.car.trust.ICarTrustAgentTokenResponseCallback;
     25 import android.content.ComponentName;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.ServiceConnection;
     29 import android.content.SharedPreferences;
     30 import android.content.pm.PackageManager;
     31 import android.os.Bundle;
     32 import android.os.IBinder;
     33 import android.os.RemoteException;
     34 import android.os.UserHandle;
     35 import android.preference.PreferenceManager;
     36 import android.util.Log;
     37 import android.widget.TextView;
     38 
     39 /**
     40  * Setup activity that binds {@link CarTrustAgentBleService} and starts the enrolment process.
     41  */
     42 public class CarEnrolmentActivity extends Activity {
     43 
     44     private static final String TAG = CarEnrolmentActivity.class.getSimpleName();
     45 
     46     private static final String SP_HANDLE_KEY = "sp-test";
     47     private static final int FINE_LOCATION_REQUEST_CODE = 42;
     48 
     49     private final ICarTrustAgentTokenResponseCallback mCarTrustAgentTokenResponseCallback =
     50             new ICarTrustAgentTokenResponseCallback.Stub() {
     51         @Override
     52         public void onEscrowTokenAdded(byte[] token, long handle, int uid) {
     53             runOnUiThread(() -> {
     54                 mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply();
     55                 Log.d(TAG, "stored new handle");
     56             });
     57 
     58             if (mBluetoothDevice == null) {
     59                 Log.e(TAG, "No active bluetooth found to add escrow token");
     60                 return;
     61             }
     62 
     63             try {
     64                 // Notify the enrolment client that escrow token has been added
     65                 mCarTrustAgentBleService.sendEnrolmentHandle(mBluetoothDevice, handle);
     66                 appendOutputText("Escrow Token Added. Handle: " + handle);
     67                 appendOutputText("Lock and unlock the device to activate token");
     68             } catch (RemoteException e) {
     69                 Log.e(TAG, "Error sendEnrolmentHandle", e);
     70             }
     71         }
     72 
     73         @Override
     74         public void onEscrowTokenRemoved(long handle, boolean successful) {
     75             appendOutputText("Escrow token Removed. Handle: " + handle);
     76         }
     77 
     78         @Override
     79         public void onEscrowTokenActiveStateChanged(long handle, boolean active) {
     80             appendOutputText("Is token active? " + active + " handle: " + handle);
     81         }
     82     };
     83 
     84     private final ICarTrustAgentBleCallback mBleConnectionCallback =
     85             new ICarTrustAgentBleCallback.Stub() {
     86         @Override
     87         public void onBleServerStartSuccess() {
     88             appendOutputText("Server started");
     89         }
     90 
     91         @Override
     92         public void onBleServerStartFailure(int errorCode) {
     93             appendOutputText("Server failed to start, error code: " + errorCode);
     94         }
     95 
     96         @Override
     97         public void onBleDeviceConnected(BluetoothDevice device) {
     98             mBluetoothDevice = device;
     99             appendOutputText("Device connected: " + device.getName()
    100                     + " address: " + device.getAddress());
    101         }
    102 
    103         @Override
    104         public void onBleDeviceDisconnected(BluetoothDevice device) {
    105             mBluetoothDevice = null;
    106             appendOutputText("Device disconnected: " + device.getName()
    107                     + " address: " + device.getAddress());
    108         }
    109     };
    110 
    111     private final ICarTrustAgentEnrolmentCallback mEnrolmentCallback =
    112             new ICarTrustAgentEnrolmentCallback.Stub() {
    113         @Override
    114         public void onEnrolmentDataReceived(byte[] token) {
    115             appendOutputText("Enrolment data received ");
    116             try {
    117                 addEscrowToken(token);
    118             } catch (RemoteException e) {
    119                 Log.e(TAG, "Error addEscrowToken", e);
    120             }
    121         }
    122     };
    123 
    124     private final ServiceConnection mServiceConnection = new ServiceConnection() {
    125         @Override
    126         public void onServiceConnected(ComponentName name, IBinder service) {
    127             mCarTrustAgentBleServiceBound = true;
    128             mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service);
    129             try {
    130                 mCarTrustAgentBleService.registerBleCallback(mBleConnectionCallback);
    131                 mCarTrustAgentBleService.registerEnrolmentCallback(mEnrolmentCallback);
    132                 mCarTrustAgentBleService.setTokenResponseCallback(
    133                         mCarTrustAgentTokenResponseCallback);
    134                 mCarTrustAgentBleService.startEnrolmentAdvertising();
    135             } catch (RemoteException e) {
    136                 Log.e(TAG, "Error startEnrolmentAdvertising", e);
    137             }
    138         }
    139 
    140         @Override
    141         public void onServiceDisconnected(ComponentName name) {
    142             if (mCarTrustAgentBleService != null) {
    143                 try {
    144                     mCarTrustAgentBleService.unregisterBleCallback(mBleConnectionCallback);
    145                     mCarTrustAgentBleService.unregisterEnrolmentCallback(mEnrolmentCallback);
    146                     mCarTrustAgentBleService.setTokenResponseCallback(null);
    147                     mCarTrustAgentBleService.stopEnrolmentAdvertising();
    148                 } catch (RemoteException e) {
    149                     Log.e(TAG, "Error unregister callbacks", e);
    150                 }
    151                 mCarTrustAgentBleService = null;
    152             }
    153             mCarTrustAgentBleServiceBound = false;
    154         }
    155     };
    156 
    157     private TextView mOutputText;
    158     private BluetoothDevice mBluetoothDevice;
    159     private ICarTrustAgentBleService mCarTrustAgentBleService;
    160     private boolean mCarTrustAgentBleServiceBound;
    161     private SharedPreferences mPrefs;
    162 
    163     @Override
    164     protected void onCreate(Bundle savedInstanceState) {
    165         super.onCreate(savedInstanceState);
    166 
    167         setContentView(R.layout.car_enrolment_activity);
    168         mOutputText = findViewById(R.id.textfield);
    169         mPrefs = PreferenceManager.getDefaultSharedPreferences(this /* context */);
    170 
    171         findViewById(R.id.start_button).setOnClickListener((view) -> {
    172             Intent bindIntent = new Intent(this, CarTrustAgentBleService.class);
    173             bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
    174         });
    175 
    176         findViewById(R.id.revoke_trust_button).setOnClickListener((view) -> {
    177             if (mCarTrustAgentBleServiceBound) {
    178                 try {
    179                     mCarTrustAgentBleService.revokeTrust();
    180                 } catch (RemoteException e) {
    181                     Log.e(TAG, "Error revokeTrust", e);
    182                 }
    183             }
    184         });
    185     }
    186 
    187     @Override
    188     protected void onResume() {
    189         super.onResume();
    190 
    191         if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) !=
    192                 PackageManager.PERMISSION_GRANTED) {
    193             requestPermissions(
    194                     new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
    195                     FINE_LOCATION_REQUEST_CODE);
    196         } else {
    197             long tokenHandle = getTokenHandle();
    198             if (tokenHandle != -1) {
    199                 Log.d(TAG, "onResume, checking handle active: " + tokenHandle);
    200                 if (mCarTrustAgentBleServiceBound) {
    201                     try {
    202                         // Due to the asynchronous nature of isEscrowTokenActive in
    203                         // TrustAgentService, query result will be delivered via
    204                         // {@link #mCarTrustAgentTokenResponseCallback}
    205                         mCarTrustAgentBleService.isEscrowTokenActive(tokenHandle,
    206                                 UserHandle.myUserId());
    207                     } catch (RemoteException e) {
    208                         Log.e(TAG, "Error isEscrowTokenActive", e);
    209                     }
    210                 }
    211             } else {
    212                 appendOutputText("No handles found");
    213             }
    214         }
    215     }
    216 
    217     @Override
    218     protected void onDestroy() {
    219         if (mCarTrustAgentBleServiceBound) {
    220             unbindService(mServiceConnection);
    221         }
    222         super.onDestroy();
    223     }
    224 
    225     private void appendOutputText(final String text) {
    226         runOnUiThread(() -> mOutputText.append("\n" + text));
    227     }
    228 
    229     private void addEscrowToken(byte[] token) throws RemoteException {
    230         if (!mCarTrustAgentBleServiceBound) {
    231             Log.e(TAG, "No CarTrustAgentBleService bounded");
    232             return;
    233         }
    234         mCarTrustAgentBleService.addEscrowToken(token, UserHandle.myUserId());
    235     }
    236 
    237     private long getTokenHandle() {
    238         return mPrefs.getLong(SP_HANDLE_KEY, -1);
    239     }
    240 }
    241