1 /* 2 * Copyright (C) 2024 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.nfc; 18 19 import android.annotation.NonNull; 20 import android.app.ActivityManager; 21 import android.app.backup.BackupManager; 22 import android.content.ApexEnvironment; 23 import android.content.Context; 24 import android.content.res.Resources; 25 import android.nfc.Constants; 26 import android.nfc.NfcFrameworkInitializer; 27 import android.nfc.NfcServiceManager; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.IBinder; 31 import android.os.Looper; 32 import android.os.RemoteException; 33 import android.os.SystemClock; 34 import android.os.SystemProperties; 35 import android.os.UserHandle; 36 import android.os.VibrationEffect; 37 import android.provider.Settings; 38 import android.se.omapi.ISecureElementService; 39 import android.se.omapi.SeFrameworkInitializer; 40 import android.se.omapi.SeServiceManager; 41 import android.text.TextUtils; 42 import android.util.AtomicFile; 43 import android.util.Log; 44 45 import com.android.nfc.cardemulation.util.StatsdUtils; 46 import com.android.nfc.dhimpl.NativeNfcManager; 47 import com.android.nfc.flags.FeatureFlags; 48 import com.android.nfc.handover.HandoverDataParser; 49 import com.android.nfc.proto.NfcEventProto; 50 51 import java.io.File; 52 import java.time.LocalDateTime; 53 54 /** 55 * To be used for dependency injection (especially helps mocking static dependencies). 56 * TODO: Migrate more classes to injector to resolve circular dependencies in the NFC stack. 57 */ 58 public class NfcInjector { 59 private static final String TAG = "NfcInjector"; 60 private static final String APEX_NAME = "com.android.nfcservices"; 61 private static final String NFC_DATA_DIR = "/data/nfc"; 62 private static final String EVENT_LOG_FILE_NAME = "event_log.binpb"; 63 64 private final Context mContext; 65 private final Looper mMainLooper; 66 private final NfcEventLog mNfcEventLog; 67 private final RoutingTableParser mRoutingTableParser; 68 private final ScreenStateHelper mScreenStateHelper; 69 private final NfcUnlockManager mNfcUnlockManager; 70 private final HandoverDataParser mHandoverDataParser; 71 private final DeviceConfigFacade mDeviceConfigFacade; 72 private final NfcDispatcher mNfcDispatcher; 73 private final VibrationEffect mVibrationEffect; 74 private final BackupManager mBackupManager; 75 private final FeatureFlags mFeatureFlags; 76 private final StatsdUtils mStatsdUtils; 77 private final ForegroundUtils mForegroundUtils; 78 private final NfcDiagnostics mNfcDiagnostics; 79 private final NfcServiceManager.ServiceRegisterer mNfcManagerRegisterer; 80 private static NfcInjector sInstance; 81 getInstance()82 public static NfcInjector getInstance() { 83 if (sInstance == null) throw new IllegalStateException("Nfc injector instance null"); 84 return sInstance; 85 } 86 87 NfcInjector(@onNull Context context, @NonNull Looper mainLooper)88 public NfcInjector(@NonNull Context context, @NonNull Looper mainLooper) { 89 if (sInstance != null) throw new IllegalStateException("Nfc injector instance not null"); 90 91 mContext = context; 92 mMainLooper = mainLooper; 93 mRoutingTableParser = new RoutingTableParser(); 94 mScreenStateHelper = new ScreenStateHelper(mContext); 95 mNfcUnlockManager = NfcUnlockManager.getInstance(); 96 mHandoverDataParser = new HandoverDataParser(); 97 mDeviceConfigFacade = new DeviceConfigFacade(mContext, new Handler(mainLooper)); 98 mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, isInProvisionMode()); 99 mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE); 100 mBackupManager = new BackupManager(mContext); 101 mFeatureFlags = new com.android.nfc.flags.FeatureFlagsImpl(); 102 mStatsdUtils = mFeatureFlags.statsdCeEventsFlag() ? new StatsdUtils() : null; 103 mForegroundUtils = 104 ForegroundUtils.getInstance(mContext.getSystemService(ActivityManager.class)); 105 mNfcDiagnostics = new NfcDiagnostics(mContext); 106 107 NfcServiceManager manager = NfcFrameworkInitializer.getNfcServiceManager(); 108 if (manager == null) { 109 Log.e(TAG, "NfcServiceManager is null"); 110 throw new UnsupportedOperationException(); 111 } 112 mNfcManagerRegisterer = manager.getNfcManagerServiceRegisterer(); 113 114 // Create UWB event log thread. 115 HandlerThread eventLogThread = new HandlerThread("NfcEventLog"); 116 eventLogThread.start(); 117 mNfcEventLog = new NfcEventLog(mContext, this, eventLogThread.getLooper(), 118 new AtomicFile(new File(NFC_DATA_DIR, EVENT_LOG_FILE_NAME))); 119 sInstance = this; 120 } 121 getContext()122 public Context getContext() { 123 return mContext; 124 } 125 getMainLooper()126 public Looper getMainLooper() { 127 return mMainLooper; 128 } 129 getNfcEventLog()130 public NfcEventLog getNfcEventLog() { 131 return mNfcEventLog; 132 } 133 getScreenStateHelper()134 public ScreenStateHelper getScreenStateHelper() { 135 return mScreenStateHelper; 136 } 137 getRoutingTableParser()138 public RoutingTableParser getRoutingTableParser() { 139 return mRoutingTableParser; 140 } 141 getNfcUnlockManager()142 public NfcUnlockManager getNfcUnlockManager() { 143 return mNfcUnlockManager; 144 } 145 getHandoverDataParser()146 public HandoverDataParser getHandoverDataParser() { 147 return mHandoverDataParser; 148 } 149 getDeviceConfigFacade()150 public DeviceConfigFacade getDeviceConfigFacade() { 151 return mDeviceConfigFacade; 152 } 153 getNfcDispatcher()154 public NfcDispatcher getNfcDispatcher() { 155 return mNfcDispatcher; 156 } 157 getVibrationEffect()158 public VibrationEffect getVibrationEffect() { 159 return mVibrationEffect; 160 } 161 getBackupManager()162 public BackupManager getBackupManager() { 163 return mBackupManager; 164 } 165 getFeatureFlags()166 public FeatureFlags getFeatureFlags() { 167 return mFeatureFlags; 168 } 169 getStatsdUtils()170 public StatsdUtils getStatsdUtils() { 171 return mStatsdUtils; 172 } 173 getForegroundUtils()174 public ForegroundUtils getForegroundUtils() { 175 return mForegroundUtils; 176 } 177 getNfcDiagnostics()178 public NfcDiagnostics getNfcDiagnostics() { 179 return mNfcDiagnostics; 180 } 181 getNfcManagerRegisterer()182 public NfcServiceManager.ServiceRegisterer getNfcManagerRegisterer() { 183 return mNfcManagerRegisterer; 184 } 185 makeDeviceHost(DeviceHost.DeviceHostListener listener)186 public DeviceHost makeDeviceHost(DeviceHost.DeviceHostListener listener) { 187 return new NativeNfcManager(mContext, listener); 188 } 189 190 /** 191 * NFC apex DE folder. 192 */ getDeviceProtectedDataDir()193 public static File getDeviceProtectedDataDir() { 194 return ApexEnvironment.getApexEnvironment(APEX_NAME) 195 .getDeviceProtectedDataDir(); 196 } 197 getLocalDateTime()198 public LocalDateTime getLocalDateTime() { 199 return LocalDateTime.now(); 200 } 201 isInProvisionMode()202 public boolean isInProvisionMode() { 203 boolean isNfcProvisioningEnabled = false; 204 try { 205 isNfcProvisioningEnabled = mContext.getResources().getBoolean( 206 R.bool.enable_nfc_provisioning); 207 } catch (Resources.NotFoundException e) { 208 } 209 210 if (isNfcProvisioningEnabled) { 211 return Settings.Global.getInt(mContext.getContentResolver(), 212 Settings.Global.DEVICE_PROVISIONED, 0) == 0; 213 } else { 214 return false; 215 } 216 } 217 checkIsSecureNfcCapable()218 public boolean checkIsSecureNfcCapable() { 219 if (mContext.getResources().getBoolean(R.bool.enable_secure_nfc_support)) { 220 return true; 221 } 222 String[] skuList = mContext.getResources().getStringArray( 223 R.array.config_skuSupportsSecureNfc); 224 String sku = SystemProperties.get("ro.boot.hardware.sku"); 225 if (TextUtils.isEmpty(sku) || !Utils.arrayContains(skuList, sku)) { 226 return false; 227 } 228 return true; 229 } 230 connectToSeService()231 public ISecureElementService connectToSeService() throws RemoteException { 232 SeServiceManager manager = SeFrameworkInitializer.getSeServiceManager(); 233 if (manager == null) { 234 Log.e(TAG, "SEServiceManager is null"); 235 return null; 236 } 237 return ISecureElementService.Stub.asInterface( 238 manager.getSeManagerServiceRegisterer().get()); 239 } 240 241 /** 242 * Kill the NFC stack. 243 */ killNfcStack()244 public void killNfcStack() { 245 System.exit(0); 246 } 247 isSatelliteModeSensitive()248 public boolean isSatelliteModeSensitive() { 249 final String satelliteRadios = 250 Settings.Global.getString(mContext.getContentResolver(), 251 Constants.SETTINGS_SATELLITE_MODE_RADIOS); 252 return satelliteRadios == null || satelliteRadios.contains(Settings.Global.RADIO_NFC); 253 } 254 255 /** Returns true if satellite mode is turned on. */ isSatelliteModeOn()256 public boolean isSatelliteModeOn() { 257 if (!isSatelliteModeSensitive()) return false; 258 return Settings.Global.getInt( 259 mContext.getContentResolver(), Constants.SETTINGS_SATELLITE_MODE_ENABLED, 0) == 1; 260 } 261 262 /** 263 * Get the current time of the clock in milliseconds. 264 * 265 * @return Current time in milliseconds. 266 */ getWallClockMillis()267 public long getWallClockMillis() { 268 return System.currentTimeMillis(); 269 } 270 271 /** 272 * Returns milliseconds since boot, including time spent in sleep. 273 * 274 * @return Current time since boot in milliseconds. 275 */ getElapsedSinceBootMillis()276 public long getElapsedSinceBootMillis() { 277 return SystemClock.elapsedRealtime(); 278 } 279 280 /** 281 * Returns nanoseconds since boot, including time spent in sleep. 282 * 283 * @return Current time since boot in milliseconds. 284 */ getElapsedSinceBootNanos()285 public long getElapsedSinceBootNanos() { 286 return SystemClock.elapsedRealtimeNanos(); 287 } 288 }