I'm trying to control Android by writing data into /dev/uinput. For example, if I enter 'A' on my desktop, the codes will write something according to key_code into uinput and Android should behave like I input an 'A' on the phone. I am following the codes in RemoteInput. I tested on Nexus 4 with JB 4.2 system. All the ioctls return positive results, which means it should work. However, when I put in an 'A', the Android only seems to refresh the virtual keyboard and does not input anything.
First, you need to "register" the supported keys using ioctl(m_fd, UI_SET_KEYBIT, key). For A, you should use KEY_A, which is defined in linux/input.h (#define KEY_A 30) and not KEYCODE_A, which is a different code. In my experience, /dev/uinput on Android works with Linux key codes.
You should:
open /dev/uinput
ioctl(m_fd, UI_SET_EVBIT, EV_KEY) - support EV_KEY event
ioctl(m_fd, UI_SET_EVBIT, EV_SYN) - support EV_SYN event
ioctl(m_fd, UI_SET_KEYBIT, key) - support key - for each keycode that you want to support
create uinput_user_dev structure and populate it, then write that structure to /dev/uinput file descriptor (see below)
call ioctl(m_fd, UI_DEV_CREATE) to create this device; the m_fd will now point to newly created device.
Do monitor logcat output and check if the device will be created successfully. It will take a generic keychar map and key layout, since no keymap is defined. If you want to define it, look into /system/usr/keychars and /system/usr/keylayout.
Create uinput device
uinput_user_dev uidev;
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-test");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1212;
uidev.id.product = 0xabab;
uidev.id.version = 3;
write(m_fd, &uidev, sizeof(uidev)
Related
Edit 10 Apr 2020
I may have misnamed what we are looking for. It may actually be the linux user name of the installed app, rather than its UID. So how should we get that programmatically?
Original question below
When we use adb shell ps even on a non rooted android device, it returns process info where the UID comes in the form u0_xxxx where x represents some arbitrary digits in hex (except for system/root processes).
For example
u0_a464 31481 894 5015336 69200 0 0 S com.example.app_uid_checker
In this example app_uid_checker is my app in user space. When trying to obtain the UID programmatically, though, I get 10464 (the decimal representation of a464), and without the u0 prefix.
I tried
package manager's getApplicationInfo()
activity manager's getAllRunningProcess()
android.os.Process.myUid()
(following suggestions in this post on SO. They all return 10464. How can I get the "full" UID? (for want of a better term, I'm not sure what the u0_a464 version of the UID should be called, as compared to the 10464 version)).
Even if we can programmatically use adb shell ps I think it may not be a good way, as adb needs developer mode to be enabled.
You need to use the geteuid(2) and getpwuid(3) to retrieve the data, as the JVM does not expose it.
extern "C" JNIEXPORT jstring JNICALL Java_com_example_GetUser_getUser(JNIEnv* env) {
uid_t uid = geteuid();
struct passwd *user;
if (uid == -1)
return NULL;
user = getpwuid(uid);
return env->NewStringUTF(user->pw_name);
}
Full working project: https://gitlab.com/hackintosh5/getuser
I'm studying the android kernel as a beginner. I can read the messages thrown from the macro ERROR() inside the function main() at system/core/init/init.c using dmesg command through adb. I observed that after calling the function open_devnull_stdio() inside main(), dmesg no longer displays the messages thrown by ERROR().
To find the reason, I started digging into the declaration of open_devnull_stdio() inside system/core/init/util.c and I found this line I can't understand
static const char *name = "/dev/__null__";
Actually there was no file named __null__ inside /dev/ in the device, but there was a file named null and I was able to grab it using adb pull and it was a 0 byte (empty) file.
So why is a file name wrapped with double underscore (__) ?
Here is the link for the util.c
There is no special purpose of using double underscore before the start, after the end or both in C. From the point of view of C the file name is just a string, the operating system is free to interpret in whatever way it chooses. From the point of view of Linux, the same applies. Underscores in file names are just characters. They are not treated differently from the letters b and t.
If I guessed right and I'm reading the same file as you (it might be a good idea to link to the source code you're reading) then it should be pretty obvious what the code does on the lines after the one you mentioned. The next lines are:
if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
fd = open(name, O_RDWR);
unlink(name);
Which creates the null device which is then opened and immediately deleted again.
I suspect this is done so that programs can run without access to the root filesystem and still be able to open the equivalent of /dev/null.
I don't know the answer but I have an idea:
The following page shows an "strace" output where /dev/__null__ is used:
https://gist.github.com/tetsu-koba/1522515
Under Linux device files have a 33-bit (?) number which identifies the device. (At least under old Linux versions) you could delete some file in /dev and you could restore it or even create it in another directory (!) when you know the 33-bit number! (So you can delete the device /dev/sda2 and create the device (not file!) /home/myuser/sda2 instead.)
The trace in the link above shows the following three lines:
mknod("/dev/__null__", S_IFCHR|0600, makedev(1, 3)) = 0
open("/dev/__null__", O_RDWR|O_LARGEFILE) = 3
unlink("/dev/__null__") = 0
These lines will create the device file /dev/__null__ (with the 33-bit number identifying /dev/null). Then it opens that file and then it removes the file again.
Maybe this is done because the tool shall be able to run both on Linux installations where the device file "/dev/null" is present (in this case the file should not be overwritten) and on installations where that file is missing (in this case a replacement file must be created using the known 33-bit number).
As other people have pointed out this just tells it's the "null device", not a regular file called "null". null is supposed to act like an information sink, not like a normal file where you dump your data to. Hope this helps.
Does anyone have any experience with contenteditable and keycodes in an (Android) WebView?
I'm writing an Android app using a WebView and need to monitor key events. I'm using jQuery, so I'm using $(document).on('keydown').
Problem is, the event received only contains useful information if it's keyCode 13/'Enter'. Things like backspace, delete, or regular characters (all of which I need to be able to monitor) return a value of 229 and 'Unidentified'.
My debugging output looks like this:
e = {"originalEvent":{"isTrusted":true},"type":"keydown","target":{"sizzle1500307408528":{"undefined":{"parentNode":[5,3,true]}}},"currentTarget":{"sizzle1500307408528":{"undefined":{"parentNode":[5,3,true]}}},"timeStamp":5361.655000000001,"jQuery310027283423097243387":true,"delegateTarget":{"location":{"ancestorOrigins":{},"origin":"file://","protocol":"file:","host":"","hostname":"","port":"","search":"","hash":""},"jQuery3100272834230972433871":{"events":{"touchend":[{"type":"touchend","origType":"touchend","guid":1,"selector":".script p","needsContext":false,"namespace":""}],"touchstart":[{"type":"touchstart","origType":"touchstart","guid":2,"selector":".script p","needsContext":false,"namespace":""}],"touchmove":[{"type":"touchmove","origType":"touchmove","guid":3,"selector":".script p","needsContext":false,"namespace":""}],"focusin":[{"type":"focusin","origType":"focus","guid":4,"selector":".script","needsContext":false,"namespace":""}],"focusout":[{"type":"focusout","origType":"blur","guid":5,"selector":".script","needsContext":false,"namespace":""}],"paste":[{"type":"paste","origType":"paste","guid":6,"selector":".script","needsContext":false,"namespace":""}],"selectionchange":[{"type":"selectionchange","origType":"selectionchange","guid":7,"namespace":""}],"input":[{"type":"input","origType":"input","guid":8,"selector":".script","needsContext":false,"namespace":""}],"keydown":[{"type":"keydown","origType":"keydown","guid":9,"selector":".script","needsContext":false,"namespace":""}]},"focusin":1,"focusout":1}},"handleObj":{"type":"keydown","origType":"keydown","guid":9,"selector":".script","needsContext":false,"namespace":""}}
e.keyCode = 229
e.key = Unidentified
My presumption is that 229 (or 0xe5) is getting returned because that's the 'Process' keyCode related to IME input (as per MDN). But regardless I don't see any way to get the key value.
(I'm also curious as to why e.KeyCode and e.keyEvent are values when there is no keyCode or keyEvent in that dump of e. But a question for another day, maybe.)
I'm having a confusing problem. I'm trying to make a Web cleint that uses WSDL.
I'm using C++ RAD Studio 10 Seattle, but the same problem occured in RAD Studio XE8(older version).
1.I create a Multi-Device Application, add one Edit component and one Button.
2.I create a WSDL Importer by changing the location of the WSDL file to : "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL" and leave all other setting to default.
3.On ButtonClick event of the button I write two lines of code :
_di_TempConvertSoap Converter = GetTempConvertSoap(true,
"http://www.w3schools.com/webservices/tempconvert.asmx?WSDL");
Edit1->Text = Converter->CelsiusToFahrenheit("32");
So after these three steps I have one unit, which is the main Unit with the Form and with the button event. And one file "tempconvert.cpp" that the WSDL Importer has generated. It quite actually just translates the WSDL code to a C++ one and defines the method to communicate with the server. In my case I have two methods : FahrenheitToCelsius() and CelsiusToFahrenheit(), in the example I use CelsiusToFahrenheit().
I compile it to 32-bit Windows platform, run it and when I click the button, the result "89.6" appears in the text of the Edit component. So this is working as expected.
But when I change the target platform to "Android" and use my mobile phone "Samsung GT-I8262" with Android 4.1.2 and run the project, it just stops and exits. I debugged the problem and it stops at the first command in "tempconvert.cpp" in RegTypes() method.
// ************************************************************************
//
// This routine registers the interfaces and types exposed by the WebService.
// ************************************************************************ //
static void RegTypes()
{
/* TempConvertSoap */
InvRegistry()->RegisterInterface(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/", L"utf-8");
InvRegistry()->RegisterDefaultSOAPAction(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/%operationName%");
InvRegistry()->RegisterInvokeOptions(__delphirtti(TempConvertSoap), ioDocument);
/* TempConvertSoap.FahrenheitToCelsius */
InvRegistry()->RegisterMethodInfo(__delphirtti(TempConvertSoap), "FahrenheitToCelsius", "",
"[ReturnName='FahrenheitToCelsiusResult']", IS_OPTN);
/* TempConvertSoap.CelsiusToFahrenheit */
InvRegistry()->RegisterMethodInfo(__delphirtti(TempConvertSoap), "CelsiusToFahrenheit", "",
"[ReturnName='CelsiusToFahrenheitResult']", IS_OPTN);
/* TempConvertHttpPost */
InvRegistry()->RegisterInterface(__delphirtti(TempConvertHttpPost), L"http://www.w3schools.com/webservices/", L"utf-8");
InvRegistry()->RegisterDefaultSOAPAction(__delphirtti(TempConvertHttpPost), L"");
}
#pragma startup RegTypes 32
Does someone have any idea why this might be happening? I tried on two other Samsung phones and it didn't work. The error that shuts the program down is "Segmentation fault(11)", and more precisely it stops at the following line of code in "System.pas" file :
u_strFromUTF8(PUChar(Dest), MaxDestChars, DestLen, MarshaledAString(Source), SourceBytes, ErrorConv);
Here is some info that I've found about the function:
u_strFromUTF8 - function that converts a UTF-8 string to UTF-16.
UCHAR is a Byte(in Delphi), so PUCHAR is a pointer to Byte.
I cannot se what could possibly go wrong with this function which apparently only converts a string.
So my question is why does the project work on Windows 32 bit version, but on Android it throws Segmentation fault(11)?
I hope I could find a solution for this problem. I will keep looking.
Thank you,
Zdravko Donev :)
UPDATE:
I disassembled the line:
InvRegistry()->RegisterInterface(__delphirtti(TempConvertSoap), L"http://www.w3schools.com/webservices/", L"utf-16");
to get :
TInvokableClassRegistry *Class = InvRegistry();
TTypeInfo *Info = __delphirtti(TempConvertSoap);
UnicodeString Namespace = "http://www.w3schools.com/webservices/";
UnicodeString WSDLEncoding = "utf-8";
Class->RegisterInterface(Info, Namespace, WSDLEncoding);
And I saw that the problem occurs when calling InvRegistry() function, but I still haven't found the problem as I cannot reach the source code of the function.
I found a solution.
I deleted the line
#pragma startup RegTypes 32
and called the method RegTypes() on my own when I create the form and it worked.
I'm trying to get my game working on Android. I've ported it with the free version of Apportable and it works quite well, but I haven't been able to implement the gyroscope feature.
CMMotionManager gets initialized but the motion updates never start (or at least handleDeviceMotion: never gets called). The motion manager's isAccelerometerActive property is always NO, but isAccelerometerAvailable is YES.
Using [NSOperationQueue mainQueue] doesn't help either.
This is how I initialize the motion manager:
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.gyroUpdateInterval = .2;
[self.motionManager startDeviceMotionUpdatesToQueue:[[NSOperationQueue alloc] init]
withHandler:^(CMDeviceMotion *motion, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self handleDeviceMotion:motion];
});
}];
It produces the following message to logcat:
E/Sensors ( 507): HAL:ERR open file /sys/bus/iio/devices/iio:device0/dmp_event_int_on to write with error 2
E/Sensors ( 507): HAL:ERR can't disable DMP event interrupt
I have no idea what this means...
I'm testing the app on Asus Nexus 7.
Is there something special I need to do to use CoreMotion with Apportable?
Edit:
Here's a simple test project I created to demonstrate the issue.
CoreMotion should work with apportable. Here is a simplified initialization and usage paradigm that I've tested on a Nexus 7 (2012).
self.motionManager = [[CMMotionManager alloc] init];
[self.motionManager startDeviceMotionUpdates];
self.motionTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:#selector(handleDeviceMotion)
userInfo:nil
repeats:YES];
Instead of using startDeviceMotionUpdatesToQueue: withHandler: to process the motion events, try explicitly accessing the deviceMotion property in a handleDeviceMotion method which will be called by the repeating timer.
-(void) handleDeviceMotion {
CMDeviceMotion *motion = [self.motionManager deviceMotion];
// use motion data accordingly
}
And don't forget to stop updates when you're done!
[self.motionManager stopDeviceMotionUpdates];
For this sort of device motion in particular, we had a fairly layered series of issues that I've (hopefully) resolved with the next SDK update. I've implemented yaw, pitch, and roll, and they seem to give relatively sane values. If you're still having issues, email sdk(#)apportable.com (delete the parens obviously) and mention me.