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.server.wifi.hal; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.net.MacAddress; 22 import android.os.RemoteException; 23 import android.os.ServiceSpecificException; 24 import android.util.Log; 25 26 import java.util.Arrays; 27 import java.util.List; 28 29 /** 30 * AIDL implementation of the IWifiApIface interface. 31 */ 32 public class WifiApIfaceAidlImpl implements IWifiApIface { 33 private static final String TAG = "WifiApIfaceAidlImpl"; 34 private android.hardware.wifi.IWifiApIface mWifiApIface; 35 private final Object mLock = new Object(); 36 private String mIfaceName; 37 WifiApIfaceAidlImpl(@onNull android.hardware.wifi.IWifiApIface apIface)38 public WifiApIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiApIface apIface) { 39 mWifiApIface = apIface; 40 } 41 42 /** 43 * See comments for {@link IWifiApIface#getName()} 44 */ 45 @Override 46 @Nullable getName()47 public String getName() { 48 final String methodStr = "getName"; 49 synchronized (mLock) { 50 if (!checkIfaceAndLogFailure(methodStr)) return null; 51 if (mIfaceName != null) return mIfaceName; 52 try { 53 String ifaceName = mWifiApIface.getName(); 54 mIfaceName = ifaceName; 55 return mIfaceName; 56 } catch (RemoteException e) { 57 handleRemoteException(e, methodStr); 58 } catch (ServiceSpecificException e) { 59 handleServiceSpecificException(e, methodStr); 60 } 61 return null; 62 } 63 } 64 65 /** 66 * See comments for {@link IWifiApIface#getBridgedInstances()} 67 */ 68 @Override 69 @Nullable getBridgedInstances()70 public List<String> getBridgedInstances() { 71 final String methodStr = "getBridgedInstances"; 72 synchronized (mLock) { 73 try { 74 if (!checkIfaceAndLogFailure(methodStr)) return null; 75 String[] instances = mWifiApIface.getBridgedInstances(); 76 if (instances == null) { 77 Log.e(TAG, methodStr + " received a null array from the HAL"); 78 return null; 79 } 80 return Arrays.asList(instances); 81 } catch (RemoteException e) { 82 handleRemoteException(e, methodStr); 83 } catch (ServiceSpecificException e) { 84 handleServiceSpecificException(e, methodStr); 85 } 86 return null; 87 } 88 } 89 90 /** 91 * See comments for {@link IWifiApIface#getFactoryMacAddress()} 92 */ 93 @Override 94 @Nullable getFactoryMacAddress()95 public MacAddress getFactoryMacAddress() { 96 final String methodStr = "getFactoryMacAddress"; 97 synchronized (mLock) { 98 if (!checkIfaceAndLogFailure(methodStr)) return null; 99 try { 100 byte[] macBytes = mWifiApIface.getFactoryMacAddress(); 101 return MacAddress.fromBytes(macBytes); 102 } catch (RemoteException e) { 103 handleRemoteException(e, methodStr); 104 } catch (ServiceSpecificException e) { 105 handleServiceSpecificException(e, methodStr); 106 } catch (IllegalArgumentException e) { 107 Log.e(TAG, methodStr + " received invalid MAC address: " + e); 108 } 109 return null; 110 } 111 } 112 113 /** 114 * See comments for {@link IWifiApIface#setCountryCode(byte[])} 115 */ 116 @Override setCountryCode(byte[] countryCode)117 public boolean setCountryCode(byte[] countryCode) { 118 final String methodStr = "setCountryCode"; 119 synchronized (mLock) { 120 try { 121 if (!checkIfaceAndLogFailure(methodStr)) return false; 122 mWifiApIface.setCountryCode(countryCode); 123 return true; 124 } catch (RemoteException e) { 125 handleRemoteException(e, methodStr); 126 } catch (ServiceSpecificException e) { 127 handleServiceSpecificException(e, methodStr); 128 } 129 return false; 130 } 131 } 132 133 /** 134 * See comments for {@link IWifiApIface#resetToFactoryMacAddress()} 135 */ 136 @Override resetToFactoryMacAddress()137 public boolean resetToFactoryMacAddress() { 138 final String methodStr = "resetToFactoryMacAddress"; 139 synchronized (mLock) { 140 try { 141 if (!checkIfaceAndLogFailure(methodStr)) return false; 142 mWifiApIface.resetToFactoryMacAddress(); 143 return true; 144 } catch (RemoteException e) { 145 handleRemoteException(e, methodStr); 146 } catch (ServiceSpecificException e) { 147 handleServiceSpecificException(e, methodStr); 148 } 149 return false; 150 } 151 } 152 153 /** 154 * See comments for {@link IWifiApIface#isSetMacAddressSupported()} 155 */ 156 @Override isSetMacAddressSupported()157 public boolean isSetMacAddressSupported() { 158 return true; // supported by default in the AIDL HAL 159 } 160 161 /** 162 * See comments for {@link IWifiApIface#setMacAddress(MacAddress)} 163 */ 164 @Override setMacAddress(MacAddress mac)165 public boolean setMacAddress(MacAddress mac) { 166 final String methodStr = "setMacAddress"; 167 synchronized (mLock) { 168 try { 169 if (!checkIfaceAndLogFailure(methodStr)) return false; 170 mWifiApIface.setMacAddress(mac.toByteArray()); 171 return true; 172 } catch (RemoteException e) { 173 handleRemoteException(e, methodStr); 174 } catch (ServiceSpecificException e) { 175 handleServiceSpecificException(e, methodStr); 176 } 177 return false; 178 } 179 } 180 checkIfaceAndLogFailure(String methodStr)181 private boolean checkIfaceAndLogFailure(String methodStr) { 182 if (mWifiApIface == null) { 183 Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); 184 return false; 185 } 186 return true; 187 } 188 handleRemoteException(RemoteException e, String methodStr)189 private void handleRemoteException(RemoteException e, String methodStr) { 190 mWifiApIface = null; 191 mIfaceName = null; 192 Log.e(TAG, methodStr + " failed with remote exception: " + e); 193 } 194 handleServiceSpecificException(ServiceSpecificException e, String methodStr)195 private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { 196 Log.e(TAG, methodStr + " failed with service-specific exception: " + e); 197 } 198 } 199