1 /* 2 * Copyright (C) 2022 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 17 package com.android.rkpdapp.interfaces; 18 19 import android.annotation.TestApi; 20 import android.hardware.security.keymint.IRemotelyProvisionedComponent; 21 import android.os.ServiceManager; 22 import android.util.Log; 23 24 import java.util.Arrays; 25 import java.util.Map; 26 import java.util.Objects; 27 28 /** 29 * Provides convenience methods for interfacing with ServiceManager class and its static functions. 30 */ 31 public class ServiceManagerInterface { 32 private static final String TAG = "RkpdSvcManagerInterface"; 33 private static SystemInterface[] sInstances; 34 private static Map<String, IRemotelyProvisionedComponent> sBinders; 35 ServiceManagerInterface()36 private ServiceManagerInterface() { 37 } 38 tryCreateSystemInterface(IRemotelyProvisionedComponent binder, String serviceName)39 private static SystemInterface tryCreateSystemInterface(IRemotelyProvisionedComponent binder, 40 String serviceName) { 41 try { 42 return new SystemInterface(binder, serviceName); 43 } catch (UnsupportedOperationException e) { 44 Log.i(TAG, serviceName + " is unsupported."); 45 return null; 46 } 47 } 48 getBinder(String serviceName)49 private static IRemotelyProvisionedComponent getBinder(String serviceName) { 50 IRemotelyProvisionedComponent binder = IRemotelyProvisionedComponent.Stub.asInterface( 51 ServiceManager.waitForDeclaredService(serviceName)); 52 if (binder == null) { 53 throw new IllegalArgumentException("Cannot find any implementation for " + serviceName); 54 } 55 return binder; 56 } 57 58 /** 59 * Gets all the instances on this device for IRemotelyProvisionedComponent as an array. The 60 * returned values each contain a binder for interacting with the instance. 61 * 62 * For testing purposes, the instances may be overridden by either setInstances or setBinders. 63 */ getAllInstances()64 public static SystemInterface[] getAllInstances() { 65 if (sBinders != null) { 66 return sBinders.entrySet().stream() 67 .map(x -> tryCreateSystemInterface(x.getValue(), x.getKey())) 68 .filter(Objects::nonNull) 69 .toArray(SystemInterface[]::new); 70 } 71 if (sInstances != null) { 72 return sInstances; 73 } 74 75 String irpcInterface = IRemotelyProvisionedComponent.DESCRIPTOR; 76 return Arrays.stream(ServiceManager.getDeclaredInstances(irpcInterface)) 77 .map(x -> { 78 String serviceName = irpcInterface + "/" + x; 79 return tryCreateSystemInterface(getBinder(serviceName), serviceName); 80 }) 81 .filter(Objects::nonNull) 82 .toArray(SystemInterface[]::new); 83 } 84 85 /** 86 * Get a specific system interface instance for a given IRemotelyProvisionedComponent. 87 * If the given serviceName does not map to a known IRemotelyProvisionedComponent, this 88 * method throws IllegalArgumentException. 89 * If the given serviceName is not supported, this method throws UnsupportedOperationException. 90 * 91 * For testing purposes, the instances may be overridden by either setInstances or setBinders. 92 */ getInstance(String serviceName)93 public static SystemInterface getInstance(String serviceName) { 94 if (sBinders != null) { 95 if (sBinders.containsKey(serviceName)) { 96 return new SystemInterface(sBinders.get(serviceName), serviceName); 97 } 98 throw new IllegalArgumentException("Cannot find any binder for " + serviceName); 99 } 100 if (sInstances != null) { 101 for (SystemInterface i : sInstances) { 102 if (i.getServiceName().equals(serviceName)) { 103 return i; 104 } 105 } 106 throw new IllegalArgumentException("Cannot find any implementation for " + serviceName); 107 } 108 109 return new SystemInterface(getBinder(serviceName), serviceName); 110 } 111 112 @TestApi setInstances(SystemInterface[] instances)113 public static void setInstances(SystemInterface[] instances) { 114 sInstances = instances; 115 } 116 117 @TestApi setBinders(Map<String, IRemotelyProvisionedComponent> binders)118 public static void setBinders(Map<String, IRemotelyProvisionedComponent> binders) { 119 sBinders = binders; 120 } 121 } 122