Process.getExclusiveCores() throws exception on certain devices - android

My Android app is currently in open beta and I am receiving crash reports from my beloved testers. Audio processing is the app's primary focus therefore the render thread is cpu intensive and time sensitive. In an attempt to achieve the best performance possible, I am reserving exclusive cores for the process by calling:
int exclusiveCores[] = {};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
exclusiveCores = android.os.Process.getExclusiveCores();
}
then sending the int array on through the JNI to be handled by the engine.
This has worked fine until recently when I received a crash report stating a RuntimeException was thrown on the getExclusiveCores() call. The device was a Samsung J7 (SM-J727T) running Android 7.0. This is the only device so far that has given me this report.
Has anyone else experienced this issue? Is this API not available for this specific device? Is there another limitation I should be checking for before calling getExclusiveCores?
The documentation states:
To support an exclusive core on a device:
Enable cpusets and configure a cpuset that contains only the top foreground application.
Ensure one core (this is the exclusive core) is reserved for threads from this cpuset.
but I am unable to find any other documentation on how to enable cpusets and configure a cpuset.
Can anyone provide an example of this implementation or point me in the right direction?
Also, I personally do not have this device and Firebase Testlab does not have this device running android 7.0 so testing any solution will have its own complications.
Thanks

I also ran into this on a Samsung Galaxy S6 running Android 7.0.
Unfortunately it looks like getExclusiveCores isn't implemented on some devices (despite being a mandatory API, specified in the Android CDD).
The best advice is to wrap calls to this method in a try/catch block and catch the RuntimeException:
try {
exclusiveCores = android.os.Process.getExclusiveCores();
} catch (RuntimeException e){
Log.w(TAG, "getExclusiveCores() is not supported on this device.");
}

Related

hidraw set-report/send-report doesn't work with Android 6.x

I have a bluetooth hid device that I need to communicate with. Target platform is Android 5.x+. Currently testing on Nexus 7 2013 tablet.
My code works fine on android 5.x, I am able to receive, send and set reports on Android 5.x.
On Android 6.x, I am only able to receive reports sent by device, but I am not able to send or set reports. It looks like my set/send report requests are silently ignored by HID/BT stack.
The code that talks to /dev/hidraw* nodes runs as a native daemon as root.
Are there any new requirements to be able to set/send reports to Bluetooth hid devices on Android 6.x? Is there any changes I could make to AOSP to allow this to work?
[Update]
Logcat says:
05-17 11:22:56.085 2455-4061/com.android.bluetooth E/bt_btif: uhid_event: Invalid size read from uhid-dev: 4108 != 4
I do not understand how reading from uhid will return only 4 bytes! First 4 bytes are supposed to contain only the type of event. Is there any scenario that will result in a read() of less than sizeof(struct uhid_event) bytes?
Could this indicate a bug in uhid driver?
I checked available kernel sources and found that hidraw driver does not contain usable source to feed reports to /dev/hidraw* nodes
I also found that Bluedroid correctly receives and sends reports internally.
Simplest method to get/set/send reports I found was to modify bluedroid to communicate directly with my App for vendor-specific reports. I integrated my daemon into Bluedroid directly.

Cannot set temperature interval on sensortag

I'm creating an android application that interfaces with the texas instruments sensortag. One of the things the app needs to do is be able to change the frequency in which the temperature is reported to the app. I am able to change it through the official TI app which is great, but I cannot seem to get it working in my app.
When viewing the official app (iOS, can't run the android one?), it shows the temperature GATT service, which contains 3 characteristics. When I inspect the characteristics discovered by my app however, it only seems to find two - the data, and the notifications. Not the interval. I have attempted to construct this characteristic myself and write it however it doesn't do anything - no error, no success, just nothing.
The steps I've taken are essentially:
bluetoothGatt.discoverServices();
...
services = bluetoothGatt.getServices();
...
BluetoothGattService service = bluetoothGatt.getService(serviceUUID);
System.out.println("Characteristic = " + service.getCharacteristic(SensorTagGatt.UUID_IRT_PERI));
The output yields null. Is there something obvious I'm missing or that I should be doing that I might not be?
EDIT:
I've installed another app onto the phone written by another developer, and using this to inspect the services and characteristics available shows that it too is unable to find it, so I'm assuming there is something wrong with the android service discovery? The official iOS app is working as expected, and showing all characteristics. Unfortunately, the official android app seems to be incompatible with the version 1.5 firmware and crashes when trying to connect but I assume it too will fail to find the characteristic.
Has anyone else run into this issue and if so been able to get around it?

Is it me, or is DevicePolicyManager.getStorageEncryptionStatus() broken?

I am trying to determine the storage encryption status of my Android device from within my application. Following the recommendations of the relevant Android Developer page, here is my code:
DevicePolicyManager mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
int encryptionStatus = mDPM.getStorageEncryptionStatus();
if (DEBUG) Log.v(TAG, "checkSecuritySettingsSufficient: encryptionStatus=" + encryptionStatus);
Here's the trouble: when I run this code on a device (I've tried it on a Motorola Droid Maxx running Android 4.4.4 and a Nexus 7 running Android 5.0.2) which I have previously encrypted, DevicePolicyManager.getStorageEncryptionStatus() will always return a value of 1, i.e. ENCRYPTION_STATUS_INACTIVE.
Android is therefore reporting that the device is not encrypted, despite the fact that the file system is definitely encrypted (I checked its status from the Settings > Security page).
Is this function broken? There doesn't seem to be any mention of that on SO or on other web sources. This leads me to believe that I am not doing something correctly with respect to DevicePolicyManager.
UPDATE After running through the encryption steps again with the Motorola device, DevicePolicyManager.getStorageEncryptionStatus() is returning the correct value, but it's still failing on the Nexus 7.
I just ran into this same issue and found out it was happening because the device had disk encryption enabled, but did not require the passcode be entered at startup. Changing the passcode, and forcing the require PIN at startup option to be true made DevicePolicyManager.getStorageEncryptionStatus() correctly return ENCRYPTION_STATUS_ACTIVE.

Solving "Package manager has died" RuntimeException

I have an Android app that should list all installed apps on a device (no root). I have tried both getInstalledApplications(0) and getInstalledPackages(0) methods of PackageManager, but on some devices, which do apparently have too many apps installed, I'm getting "Package manager has died" RuntimeException (I receive them via error reporting service of Google Play). This is due to a well-known limitation of 1MB per 1 call in IPC used internally by Android.
How to workaround this? I don't mind to request the long list by chunks, but I don't see any means for that. Only 2 abovementioned methods are available.
The issue has been fixed since Android 5.1. You may find details in the Android issuetracker.

Android Bluetooth IOException:connection refused

Alright here's the deal. I got two Galaxy Nexus phones both with bluetooth enabled.
I've written a bluetooth connection management app that I use for device discovery and connectivity. It also outputs all the available UUIDs the devices can support.
Looking from http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm the following standard UUIDs are exposed from Galaxy Nexus devices.
0x1116 - NAP
0x112f - PBAP (Phonebook Access Profile)
0x111f - HFP (Hands free)
0x1105 - OPP (Object Push Profile)
0x1112 - HSP (Headset Profile)
0x110c - AVRCP
0x110a - A2DP
I am trying to connect via the OPP profile (UUID 00001105-0000-1000-8000-00805F9B34FB) and push objects (files) between the devices. I've gone though the entire Android API documentation on how to discover, pair/bond (threading etc.) and manage all bluetooth connections. I've managed to successfully connect and talk to a legacy board device via the SPP (0x1101) profile.
However, when I try to use socket.connect() between the two galaxy nexus phones, the pairing dialog shows up and I click Pair button on both devices. After that, I immediately get a Connection Refused IOException. Note that after pairing has occurred once I never get asked again which makes sense since the secure link is cached.
If I can't connect to these standard profiles using these standard UUIDs why are they exposed? How can I connect from my app to any of these profiles and interact with them? Is it because my app is not somehow trusted? What's weird is that even the Share functionality on Android does not work at all either. Is this something completely broken on Android?
Please avoid giving me hints to use the "well known UUID SPP one 0x1101" like the docs say. This is not what I want. I have a fairly good understanding of how this stuff works and I am looking for a real solution or explanation of the problem.
I've seen the typical "reflection" solution but I do not understand why is this still a problem on Android? Why do people use reflection to make this work? Can we file a bug on Android to fix this?
If those UUIDs are standard any app should be able to connect and interact with them. Why is this an issue and why do I get this exception?
Thanks in advance.
UPDATE
So for some reason the object push in the Android system started working. I actually attempted to connect via my app and it was not working. Then, I went to the Contacts app and tried to share a contact which magically worked. Then, I went back to my app and it now it works...wow. That is very weird and there must be an explanation to this.
I ran into this same issue and managed to find a solution that worked for me.
In my case I using three different test devices (Nexus 5, Galaxy S4, Note 2) and for some reason, the Note 2 wouldn't connect to my Bluetooth module yet the other two would.
The reasoning I've found is that Bluetooth drivers vary, and slightly different connection methods are needed to create a connection between different devices.
The three methods I use are called 'Secure', 'Insecure' and 'Reflection method'/'hax'.
switch(connType)
{
case Secure:
tmpSocket = device.createRfcommSocketToServiceRecord(_uuid);
break;
case Insecure:
tmpSocket = device.createInsecureRfcommSocketToServiceRecord(_uuid);
break;
case Hax:
Method createSocket = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
tmpSocket = (BluetoothSocket)createSocket.invoke(device, Integer.valueOf(1));
break;
}
In my case, the Secure mode worked for both the Nexus 5 and Galaxy S4 however it didn't work for the Note 2.
After some testing I discovered the Note 2 only works using 'Insecure' mode, so to cater to this, I basically attempt a connection and cycle through the different modes if necessary. When attempting a different connection mode I simply prompt 'retrying connection'. So, if the connection fails using secure, then I will attempt using Insecure and then using the reflection method.
I haven't run into the case where one of these three methods haven't worked.
Have you tried using a nonstandard profile? i.e. a custom UUID just for your app. This will also help you know your are (most likely) only connecting to your own app rather than some other app that is registered with the same profile.
From my experience, Bluetooth pairing is very buggy for the first pair attempt. However, using a custom UUID helps this somewhat.
The reflection method (I think) was originally an attempt to fix a bug with a specific device, however I think some people found success in using it elsewhere as well. The device was called the Spica or something similar.
As one of the comments also posted, I would also try connecting again after failing.
Basically write code that plans to fail the first attempt, but then the code tries to connect again in 5 seconds if there was a failure.
These are imperfect solutions but Bluetooth implementation on Android is also imperfect (IMHO). Hope that helps
EDIT
Based on the question update and comments:
I agree something is definitely buggy. Part of the problem I think is the BT drivers vary and each has a different BT stack with different quirks. I also found a question that makes use of both the reflection method AND custom UUID, AND other standard methods. This seems extreme to me but it does cover the most ground. Unfortunately as app developers we have no control over the low level stack/code/drivers.
I have found with my two Bluetooth sharing apps that the first pairing is always tricky.
I'm glad to know it's not just me.

Categories

Resources