AOSP NFC device call flow from HAL to Application Framework Layer - android

I'm studying the NFC code of Google Pixel AOSP build (android-8.0.0_r3). I can understand the call flow from kernel all the way to Android hardware module system\nfc\halimpl\pn54x\nfc_nci.c as following:
struct nfc_nci_module_t HAL_MODULE_INFO_SYM = {
.common =
{
.tag = HARDWARE_MODULE_TAG,
.module_api_version = 0x0100, /* [15:8] major, [7:0] minor (1.0) */
.hal_api_version = 0x00, /* 0 is only valid value */
.id = NFC_NCI_HARDWARE_MODULE_ID,
.name = "NXP PN54X NFC NCI HW HAL",
.author = "NXP Semiconductors",
.methods = &nfc_module_methods,
},
};
This hardware module is loaded via hw_get_module(NFC_NCI_HARDWARE_MODULE_ID) found it in hardware/interface/nfc/1.0/default/nfc.cpp : HIDL_FETCH_INfc(...). Now I'm stuck here unable to find where in the AOSP invoked HIDL_FETCH_INfc(...)and how does it link to the next layer?

For android services that interact with hardware it connects in the following way.
In the nfc.cpp there should be a functions that are similar to:
JNINativeMethod method_table[]= {
{"external_name","(I)Z)",(void*)internal_name},
};
int register_android_server_FlexcanService(JNIEnv* env)
{
return jniRegisterNativeMethods(env,"com/android/server/MyService",method_table,NELEM(method_table));
}
This jniRegisterNativeMethods is called in onload.cpp and nfc.cpp is added to the Android.mk in the same folder
Then in the java package com.android.server.MyService (core/java/com/android/server) there will be a call to the native function:
public static native boolean external_name(int someVar);
From there there will be an .aidl binder file to expose the service methods to the SDK and eventually into top level Android apps.

In Android 7.x, NFC JNI locates at packages/apps/Nfc/nci/jni/. I haven't checked Android 8.x source, but I think it's still there.

Related

TFlite with delegate gpu is give wrong result

I'm trying to inference my tflite model on c++ code at an embedded device.
So, I type simple tflite inference code which is using GPU.
And I cross-compile in my PC and run at the embedded device which is running android.
However, (1) If I use delegate gpu option, c++ codes give random results.
(2) It has given same input, but the results changed every time.
(3) When I turn off the gpu option, it gives me a correct results.
When I test my tflite model in python, it gives the correct output.
So I think the model file has no problem.
Should I re-build TensorFlow-lite because I use a prebuilt .so file? or Should I change the GPU option?
I don't know what should I check more.
Please Help!
Here is my C++ code
// Load model
std::unique_ptr<tflite::FlatBufferModel> model =
tflite::FlatBufferModel::BuildFromFile(model_file.c_str());
// Build the interpreter
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model, resolver)(&interpreter);
// set delegate option
bool use_gpu = true;
if(use_gpu)
{
TfLiteDelegate* delegate;
auto options = TfLiteGpuDelegateOptionsV2Default();
options.inference_preference = TFLITE_GPU_INFERENCE_PREFERENCE_FAST_SINGLE_ANSWER;
options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_AUTO;
delegate = TfLiteGpuDelegateV2Create(&options);
interpreter->ModifyGraphWithDelegate(delegate);
}
interpreter->AllocateTensors();
// set input
float* input = interpreter->typed_input_tensor<float>(0);
for(int i=0; i<width*height*channel; i++)
*(input+i) = 1;
TfLiteTensor* output_tensor = nullptr;
// Inference
interpreter->Invoke();
// Check output
output_tensor = interpreter->tensor(interpreter->outputs()[0]);
printf("Result : %f\n",output_tensor->data.f[0]);
//float* output = interpreter->typed_output_tensor<float>(0);
//printf("output : %f\n",*(output));
Luckily, I found the answer.
This was caused by the mismatch of the NDK version. (The prebuilt so file I used is built another version)
After unifying the NDK version to 21, it was tested again, and it worked normally.
In my case same application using gpu on S10 lite was not working but on S22,S21 Ultra 5G was working.
So you can consider running on different chipset configuration on different devices with same application.

Titanium Hyperloop access to android.os.SystemProperties

I have been trying a ( i hope) simple bit of Android hyperloop code directly within a titanium project (using SDK 7.0.1.GA and hyperloop 3).
var sysProp = require('android.os.SystemProperties');
var serialNumber = sysProp.get("sys.serialnumber", "none");
But when the app is run it reports
Requested module not found:android.os.SystemProperties
I think this maybe due to the fact that when compiling the app (using the cli) it reports
hyperloop:generateSources: Skipping Hyperloop wrapper generation, no usage found ...
I have similar code in a jar and if I use this then it does work, so I am wondering why the hyperloop generation is not being triggered, as I assume that is the issue.
Sorry should have explained better.
This is the jar source that I use, the extraction of the serial number was just an example (I need access to other info manufacturer specific data as well), I wanted to see if I could replicate the JAR functionality using just hyperloop rather that including the JAR file. Guess if it's not broke don't fix it, but was curious to see if it could be done.
So with the feedback from #miga and a bit of trial and error, I have come up with a solution that works really well and will do the method reflection that is required. My new Hyperloop function is
function getData(data){
var result = false;
var Class = require("java.lang.Class");
var String = require("java.lang.String");
var c = Class.forName("android.os.SystemProperties");
var get = c.getMethod("get", String.class, String.class);
result = get.invoke(c, data, "Error");
return result;
}
Where data is a string of the system property I want.
I am using it to extract and match a serial number from a Samsung device that is a System Property call "ril.serialnumber" or "sys.serialnumber". Now I can use the above function to do what I was using the JAR file for. Just thought I'd share in case anyone else needed something similar.
It is because android.os.SystemProperties is not class you can import. Check the android documentation at https://developer.android.com/reference/android/os/package-summary.html
You could use
var build = require('android.os.Build');
console.log(build.SERIAL);
to access the serial number.

How to wake up an Android Embedded Board from Suspend by using a GPIO

I am currently working on porting Android 4.4 (Kitkat) on an embedded system (Freescale i.MX6 based). In order to start my development, I used a few development kits (Wandboard, Boundary Device's BD-SL).
While working on the power management of my custom board, I had no trouble to put the devkits in suspend. However, I couldn't find how to wake them from sleep (other than power cycling them). The expected way of waking the system would be by getting an interrupt on a GPIO (e.g. the on-off button on an Android based phone).
I wanted to know what was the usual way to wake up an android device from suspend with a GPIO's interrupt. Though the question may seem trivial, I had trouble gathering all the information I needed from various searches on Google and specialized forums. I found a lot of information but nothing that covered the whole subject. Probably because I was missing the required background, I had trouble putting everything together without a code example. I guessed I was not the only one in this situation, thus this post.
Here are some of the information I found:
Android PowerPanager and wake locks
Android Power Management
Android Power Management on i.MX6DQ/DL
Android Input
In the end, I was digging too deep. The code example was right under my nose. Everything I needed was in the BD-SL devkit's board specific code (can be found in the BD-SL source tree in mydroid/BD-SL-i.MX6/kernel_imx/arch/arm/mach-mx6/board-mx6_nitrogen6x.c)
This code is specific to the Freescale i.MX6 provided kernel but the different parts should easily be ported/Adapted to other Android Embedded Platforms.
GPIO define. I am skipping the GPIO pin mux for simplicity. The pin needs to be multiplexed to the GPIO functionality:
#define GP_ONOFF_KEY IMX_GPIO_NR(2, 3)
Definition of the input key
#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
{ \
.gpio = gpio_num, \
.type = EV_KEY, \
.code = ev_code, \
.active_low = act_low, \
.desc = "btn " descr, \
.wakeup = wake, \
}
static struct gpio_keys_button buttons[] = {
GPIO_BUTTON(GP_ONOFF_KEY, KEY_POWER, 1, "key-power", 1),
};
Definition of the corresponding platform data and platform device:
static struct gpio_keys_platform_data button_data = {
.buttons = buttons,
.nbuttons = ARRAY_SIZE(buttons),
};
static struct platform_device button_device = {
.name = "gpio-keys",
.id = -1,
.num_resources = 0,
.dev = {
.platform_data = &button_data,
}
};
Registering of the platform device
static void __init add_device_buttons(void)
{
platform_device_register(&button_device);
}
/*!
* Board specific initialization.
*/
static void __init board_init(void)
{
//...
add_device_buttons();
//...
}
And for completeness, the initialize data structure that points to the Board specific initialization
/*
* initialize data structure.
*/
MACHINE_START(MX6_NITROGEN6X, "Boundary Devices Nitrogen6X/SABRE Lite Board")
/* Maintainer: Boundary Devices */
.boot_params = MX6_PHYS_OFFSET + 0x100,
.fixup = fixup_mxc_board,
.map_io = mx6_map_io,
.init_irq = mx6_init_irq,
.init_machine = board_init,
.timer = &timer,
.reserve = reserve,
MACHINE_END

how does the control goes to DT_MACHINE_START in android linux kernel for arm board

`DT_MACHINE_START(MSM8974_DT, "Qualcomm MSM 8974 (Flattened Device Tree)")
.map_io = msm8974_map_io,
.init_irq = msm_dt_init_irq,
.init_machine = msm8974_init,
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm8974_dt_match,
.reserve = msm_8974_reserve,
.init_very_early = msm8974_init_very_early,
.restart = msm_restart,
.smp = &msm8974_smp_ops,
MACHINE_END`
This DT_MACHINE_START macro is there in one of board files for a Qualcomm chipset 8974.
My question is that how the control comes to this MACHINE START as ".init_machine" is getting called.
The Linux kernel creates an ARRAY using section magic and linker scripts and the boot loader must pass the key MSM8974_DT to Linux. Linux init code looks up the machine structure and calls these function pointers at appropriate times during initialization. See arch/arm/kernel/setup.c for the call location.
See similar: SO MACHINE_START macro. The current arch.h has definitions and vmlinux.lds.S has the linker section .init.arch.info.
How is control handed to the MACHINE START's ".init_machine"?
This call is from customize_machine in the current Linux source.
static int __init customize_machine(void)
{
/*
* customizes platform devices, or adds new ones
* On DT based machines, we fall back to populating the
* machine from the device tree, if no callback is provided,
* otherwise we would always need an init_machine callback.
*/
of_iommu_init();
if (machine_desc->init_machine)
machine_desc->init_machine(); /** HERE - calls your routine **/
#ifdef CONFIG_OF
else
of_platform_populate(NULL, of_default_bus_match_table,
NULL, NULL);
#endif
return 0;
}
The structure pointer machine_desc is matched earlier in the init code as above.

How to invoke an app from another app in flex mobile

Is there a way to open one app from another app in Air? Example: I open app A which contains a button that opens app B when clicked. Suppose both A and B are separated apps that are installed in the device and that this device could be a PlayBook, an Ipad or an Android tablet.
Thanks.
You'd have to go the Air Native Extension(ANE) route. Either create one ANE solution for iOS and Android each, or one ANE that abtracts the functionality into one solution. How to launch app A from app B on Android is not the same as on iOS. See this answer in SO.
To implement it on Android, you'd wraps the native Android Java solution in a ANE. The native Java code uses the package name of app B to launch app B from app A:
Intent intent = getPackageManager().getLaunchIntentForPackage("com.yourdoman.yourapp");
startActivity(intent);
Here is a video tutorial on how to launch an Activity through an ANE which you can build on to create your ANE. You'd have to tailor the solution to launch by domain instead of Activity.
Since I really don't know the specifics of what you are trying to do, I think I should point you here: http://www.riaspace.com/2011/08/defining-custom-url-schemes-for-your-air-mobile-applications/ It is the best answer to the question that I am aware of.
private function getHostName() : void
{
if (NativeProcess.isSupported)
{
var OS : String = Capabilities.os.toLocaleLowerCase();
var file : File;
if (OS.indexOf('win') > -1)
{
// Executable in windows
file = new File('C:\\Windows\\System32\\hostname.exe');
}
else if (OS.indexOf('mac') > -1 )
{
// Executable in mac
}
else if (OS.indexOf('linux'))
{
// Executable in linux
}
var nativeProcessStartupInfo : NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process : NativeProcess = new NativeProcess();
process.addEventListener(NativeProcessExitEvent.EXIT, onExitError);
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutput);
process.start(nativeProcessStartupInfo);
process.closeInput();
}
}
private function onOutput(event : ProgressEvent) : void
{
var strHelper : StringHelper = new StringHelper();
formStationID.text = event.target.standardOutput.readUTFBytes(event.target.standardOutput.bytesAvailable);
formStationID.text = strHelper.trimBack(formStationID.text, "\n");
formStationID.text = strHelper.trimBack(formStationID.text, "\r");
}
This code gets the workstation name. I have heard this can be done on IOS and Android, but I haven't found any proof of that yet.

Categories

Resources