blob: f1a5d06e965dc4f7ac6f99fb4c1ee63c66062cda [file]
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.nfc;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.backup.BackupManager;
import android.content.ApexEnvironment;
import android.content.Context;
import android.content.res.Resources;
import android.nfc.Constants;
import android.nfc.NfcFrameworkInitializer;
import android.nfc.NfcServiceManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.provider.Settings;
import android.se.omapi.ISecureElementService;
import android.se.omapi.SeFrameworkInitializer;
import android.se.omapi.SeServiceManager;
import android.text.TextUtils;
import android.util.AtomicFile;
import android.util.Log;
import com.android.nfc.cardemulation.util.StatsdUtils;
import com.android.nfc.dhimpl.NativeNfcManager;
import com.android.nfc.flags.FeatureFlags;
import com.android.nfc.handover.HandoverDataParser;
import com.android.nfc.proto.NfcEventProto;
import java.io.File;
import java.time.LocalDateTime;
/**
* To be used for dependency injection (especially helps mocking static dependencies).
* TODO: Migrate more classes to injector to resolve circular dependencies in the NFC stack.
*/
public class NfcInjector {
private static final String TAG = "NfcInjector";
private static final String APEX_NAME = "com.android.nfcservices";
private static final String NFC_DATA_DIR = "/data/nfc";
private static final String EVENT_LOG_FILE_NAME = "event_log.binpb";
private final Context mContext;
private final Looper mMainLooper;
private final NfcEventLog mNfcEventLog;
private final RoutingTableParser mRoutingTableParser;
private final ScreenStateHelper mScreenStateHelper;
private final NfcUnlockManager mNfcUnlockManager;
private final HandoverDataParser mHandoverDataParser;
private final DeviceConfigFacade mDeviceConfigFacade;
private final NfcDispatcher mNfcDispatcher;
private final VibrationEffect mVibrationEffect;
private final BackupManager mBackupManager;
private final FeatureFlags mFeatureFlags;
private final StatsdUtils mStatsdUtils;
private final ForegroundUtils mForegroundUtils;
private final NfcDiagnostics mNfcDiagnostics;
private final NfcServiceManager.ServiceRegisterer mNfcManagerRegisterer;
private static NfcInjector sInstance;
public static NfcInjector getInstance() {
if (sInstance == null) throw new IllegalStateException("Nfc injector instance null");
return sInstance;
}
public NfcInjector(@NonNull Context context, @NonNull Looper mainLooper) {
if (sInstance != null) throw new IllegalStateException("Nfc injector instance not null");
mContext = context;
mMainLooper = mainLooper;
mRoutingTableParser = new RoutingTableParser();
mScreenStateHelper = new ScreenStateHelper(mContext);
mNfcUnlockManager = NfcUnlockManager.getInstance();
mHandoverDataParser = new HandoverDataParser();
mDeviceConfigFacade = new DeviceConfigFacade(mContext, new Handler(mainLooper));
mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, isInProvisionMode());
mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE);
mBackupManager = new BackupManager(mContext);
mFeatureFlags = new com.android.nfc.flags.FeatureFlagsImpl();
mStatsdUtils = mFeatureFlags.statsdCeEventsFlag() ? new StatsdUtils() : null;
mForegroundUtils =
ForegroundUtils.getInstance(mContext.getSystemService(ActivityManager.class));
mNfcDiagnostics = new NfcDiagnostics(mContext);
NfcServiceManager manager = NfcFrameworkInitializer.getNfcServiceManager();
if (manager == null) {
Log.e(TAG, "NfcServiceManager is null");
throw new UnsupportedOperationException();
}
mNfcManagerRegisterer = manager.getNfcManagerServiceRegisterer();
// Create UWB event log thread.
HandlerThread eventLogThread = new HandlerThread("NfcEventLog");
eventLogThread.start();
mNfcEventLog = new NfcEventLog(mContext, this, eventLogThread.getLooper(),
new AtomicFile(new File(NFC_DATA_DIR, EVENT_LOG_FILE_NAME)));
sInstance = this;
}
public Context getContext() {
return mContext;
}
public Looper getMainLooper() {
return mMainLooper;
}
public NfcEventLog getNfcEventLog() {
return mNfcEventLog;
}
public ScreenStateHelper getScreenStateHelper() {
return mScreenStateHelper;
}
public RoutingTableParser getRoutingTableParser() {
return mRoutingTableParser;
}
public NfcUnlockManager getNfcUnlockManager() {
return mNfcUnlockManager;
}
public HandoverDataParser getHandoverDataParser() {
return mHandoverDataParser;
}
public DeviceConfigFacade getDeviceConfigFacade() {
return mDeviceConfigFacade;
}
public NfcDispatcher getNfcDispatcher() {
return mNfcDispatcher;
}
public VibrationEffect getVibrationEffect() {
return mVibrationEffect;
}
public BackupManager getBackupManager() {
return mBackupManager;
}
public FeatureFlags getFeatureFlags() {
return mFeatureFlags;
}
public StatsdUtils getStatsdUtils() {
return mStatsdUtils;
}
public ForegroundUtils getForegroundUtils() {
return mForegroundUtils;
}
public NfcDiagnostics getNfcDiagnostics() {
return mNfcDiagnostics;
}
public NfcServiceManager.ServiceRegisterer getNfcManagerRegisterer() {
return mNfcManagerRegisterer;
}
public DeviceHost makeDeviceHost(DeviceHost.DeviceHostListener listener) {
return new NativeNfcManager(mContext, listener);
}
/**
* NFC apex DE folder.
*/
public static File getDeviceProtectedDataDir() {
return ApexEnvironment.getApexEnvironment(APEX_NAME)
.getDeviceProtectedDataDir();
}
public LocalDateTime getLocalDateTime() {
return LocalDateTime.now();
}
public boolean isInProvisionMode() {
boolean isNfcProvisioningEnabled = false;
try {
isNfcProvisioningEnabled = mContext.getResources().getBoolean(
R.bool.enable_nfc_provisioning);
} catch (Resources.NotFoundException e) {
}
if (isNfcProvisioningEnabled) {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) == 0;
} else {
return false;
}
}
public boolean checkIsSecureNfcCapable() {
if (mContext.getResources().getBoolean(R.bool.enable_secure_nfc_support)) {
return true;
}
String[] skuList = mContext.getResources().getStringArray(
R.array.config_skuSupportsSecureNfc);
String sku = SystemProperties.get("ro.boot.hardware.sku");
if (TextUtils.isEmpty(sku) || !Utils.arrayContains(skuList, sku)) {
return false;
}
return true;
}
public ISecureElementService connectToSeService() throws RemoteException {
SeServiceManager manager = SeFrameworkInitializer.getSeServiceManager();
if (manager == null) {
Log.e(TAG, "SEServiceManager is null");
return null;
}
return ISecureElementService.Stub.asInterface(
manager.getSeManagerServiceRegisterer().get());
}
/**
* Kill the NFC stack.
*/
public void killNfcStack() {
System.exit(0);
}
public boolean isSatelliteModeSensitive() {
final String satelliteRadios =
Settings.Global.getString(mContext.getContentResolver(),
Constants.SETTINGS_SATELLITE_MODE_RADIOS);
return satelliteRadios == null || satelliteRadios.contains(Settings.Global.RADIO_NFC);
}
/** Returns true if satellite mode is turned on. */
public boolean isSatelliteModeOn() {
if (!isSatelliteModeSensitive()) return false;
return Settings.Global.getInt(
mContext.getContentResolver(), Constants.SETTINGS_SATELLITE_MODE_ENABLED, 0) == 1;
}
}