Send emulator console commands during Espresso test - android

Google explains how to control many parameters of an Android emulator, like the current charge of the battery, the sensor input and so on here: https://developer.android.com/studio/run/emulator-console.html .
I would like to create an Espresso test that changes these parameters of an emulator during a test, is this possible? I know that there is the following method:
InstrumentationRegistry.getInstrumentation().uiAutomation
.executeShellCommand("someShellCommand")
This method can be called during a test, but for changing system parameters of an emulator I first have to login via telnet localhost 5554 and only then can I manipulate the emulator parameters like, for example, so: power capacity 30, which changes the power of the battery to 30%. How can I do this during an Espresso test?

You can try
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand("dumpsys battery set level 30");
to change the battery level. Other values or settings may require different commands.
Note: It is your responsibility to close the returned file descriptor once you are done reading.

Related

Automatically configure Android settings?

At work, we have an Android-based infotainment system that we're constantly deploying new versions to, on a half-dozen different test benches. The deployment script does the moral equivalent of:
for apk in ${apk_files}; do
adb install -r ${apk]
done
After this, we need to manually execute the following steps:
Set the home app to be one of our just-installed applications (Always, not Just Once)
Become a developer, and enable the Stay Awake option
Select the Google TTS engine for text-to-speech functionality rather than Pico
Executing these steps after each deploy is a giant PITA. People often forget one or more steps, and leave the test bench in a non-working state. This results in a bunch of 'bogus' bug reports that waste everbody's time.
Is there some way (using adb, perhaps) that we can automate these steps?
You can disable other home apps with adb shell pm disable .... I don't think there's a command line option to set apps as default. I remember looking into this before and there was a "preferred application" XML file where this was stored. If you want to look into it, the magic happens in PackageManagerService.addPreferredActivityInternal(). Looks like it writes the data to a file on disk: package-restrictions.xml. I suppose it's possible you could figure out the format thereof and write the file (you'd need root).
This is controlled by a system settings, "stay_on_while_plugged_in". You can set it using adb shell settings system put ....
The TTS engine is stored in a secure setting, "tts_default_synth". You can see the value like,
$ adb shell settings get secure tts_default_synth com.svox.pico
com.svox.pico
And you can set it with adb shell settings put secure "tts_default_synth" <the value>.
I noticed that if the value was not been previously set, when you get the value using the settings command you get null and it's not listed in settings list, even though there is a default value. As of Android 6 (I think), settings are no longer in a DB but rather are stored in XML files in /data/system/users/0/settings_*.xml. You can see the values therein.

android 6.0.1 force wifi connection with no internet access

this has many similar questions (google for: "no internet access detected. won't automatically reconnect." or: android force wifi connection programmatically).
i thought i had a answer here, but it stopped working after installing 6.0.1 updates (i have may 1 security patches).
seems like this is a behaviour change.
i have some 2013 nexus 7's with 6.0.1 that run a kiosk type app and want to connect programmatically to a specific wireless network that has no internet connection. each tablet has a unique static ip address of the form: 192.168.0.xx. i use the normal java socket constructors and check to see if the interface is up using: NetworkInterface.getNetworkInterfaces().
a manual connection has been made. sometimes there is a dialog that asks whether or not you want to always connect. i always check yes.
but the wifi says: "no internet access detected. won't automatically reconnect" after the router cycles power.
doing a disconnect, enable, reconnect does not work. at best it gets: ip6-localhost/::1.
has anyone had any luck using a request object, or bindProcessToNetwork?
edit: related.
edit: the problem seems to be with: CAPTIVE_PORTAL_DETECTION_ENABLED - this string seems to be defined in the source:
public static final String
CAPTIVE_PORTAL_DETECTION_ENABLED = "captive_portal_detection_enabled";
...
MOVED_TO_GLOBAL.add(Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED);
but throws" android.provider.Settings$SettingNotFoundException: captive_portal_detection_enabled when used explicitly and is not visible to android studio.
also, doing a settings list global does not contain the constant.
edit doing a adb shell settings put global captive_portal_detection_enabled 0 does seem to work, but this can not be done in the field when the router cycles power. this value seems to persist when the tablet cycles power. and now this value shows up in a settings list global. also, using the raw string: Settings.Global.getInt(getContentResolver(),"captive_portal_detection_enabled"); now returns 0.
edit: looks like setting it requires: android.permission.WRITE_SECURE_SETTINGS, but of course this fails when put into the manifest since we are not a system app.
edit: trying to exec the shell command throws: java.lang.SecurityException, so it looks like you need to issue the command from adb :(
thanks
Could you try and set the global setting captive_portal_detection_enabled to 0 (false).
What's actually happening is that by default, everytime you connect to a wifi, the FW will test against a server (typically google) to see if it's a captive wifi (needs login). So if your wifi is not connected to google, this check will fail. After that, the device knows that wifi has no internet connection and simply will not autoconnect to it.
Setting this setting to 0, will avoid this check.
Programatically Settings.Global.putInt(getContentResolver(), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0);
You can do it through adb for testing purposes:
adb shell settings put global captive_portal_detection_enabled 0
And retrieve it's value like this:
adb shell settings list global | grep "captive"
IMHO this is not very nice thing to do, since you are changing a setting for the user and many FWs don't provide even an advanced setting to enable/disable this by the user itself. (Google doesn't). But maybe it suits your needs.
Hope it helps!
A non-root solution which is a kind of hack tech. :P
Reboot phone, connect to the non-Internet Wifi;
Go to Settings and create a new user;
Continue, continue, and continue until you see "Checking connection";
As soon as you see "checking connection", switch off your phone;
Switch on your phone again, you will be in "Owner" user, keep it;
Toggle Wifi, and the exclamation mark should disappear quickly :)
Remove that new user or just leave it there;
I don't know why, but it works...

Bluetooth control signals (DTR, DSR, RTS, CTS) on Android

I would like to remotely reprogram my Arduino via Android over Bluetooth SPP. The first step is to reset the ATMEGA microcontroller. This is accomplished on the Arduino by toggling the DTR line. Is there any API to control the Bluetooth SPP control lines from the Android environment?
Also it is supported by SPP in general to send or receive the control signals (DTR, DSR, RTS, CTS) I do not know any API or library for android right know, but as you just want to reset your controller...
If it is o.k. for you to change your firmware you can also create your own reset-command that can be received on your UART (over SPP).
If you receive that command you could call something like
asm("jmp 0x3800");
where you have to modify the jmp-address to point to your bootloader.
You also might want to change your interrupt vector to point to your bootloader.
Or enable your watchdog and call
while(1);
This will also automatically change the interrupt vector to the bootloader's interrupt vector and reset all SFRs. - But it is a little bit slower and the bootloader's interrupt vector must be choosen in the Fuse Bits.
I realise that this is not what you wanted, but you could always flash a new bootloader with a longer timeout and manually press the reset button before starting programming.
The new Arduino bootloader (optiboot) fits in 512B (versus the 2K of the old one) so you have extra space available to your projects; has smart boot detection, so it only enters the bootloader when the reset button is pressed; and you can extend the timeout by editing the watchdog timeout value in the source (around line 267 in optiboot.c).
// Set up watchdog to trigger after 500ms (changed to 2s!)
watchdogConfig(WATCHDOG_2S);

Simulate low battery & low memory in Android

In order to generate the notifications i need to know about how to generate the low battery and low memory interrupts programmatically. Can any one please provide your suggestions.I am aware of Intents.
To trigger your onTrimMemory callbacks:
adb shell am send-trim-memory <process-name> <level>
e.g. adb shell am send-trim-memory com.example.app MODERATE
Low memory can also be simulated using Background process limit under the device developer options.
Go to Settings > Developer options. Under the app section change the Background process limit to No background processes
Now your activity will be killed every time you switch to another app. Useful for testing state saving and state restoration.
yes, this api triggers the same callback you would get if you registered a context to ComponentCallback2, specifically the ComponentCallback2#onTrimMemory this wasn't mentioned here, so I thought I'd make it clear. The syntax for this command is:
am send-trim-memory [--user <USER_ID>] <PROCESS> [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]
Note: this command is only available on devices running Marshmallow+
On the Android Emulator you can set the power status by connecting to the Emulator console and using the power command.
As far as low memory goes, you just need to make sure that your application can handle being killed without warning when it is in the background. Testing this is one of the very few cases that actually call for a Task Manager on Android, or if you're running Android 2.2 you can kill applications via Settings.
There are ways of reducing the memory available to applications but I think they're unnecessary.
To simulate low Battery warning, try this command in the way answered by Frank:
power capacity 10 // It will set the battery level into 10%
For low Memory:
ulimit -Sv 15000 //The current memory limit will set to 15000 Kb
You can use the emulator menu. Just telnet to localhost on the port of your emulator (default is 5554) and then type help. Follow the instructions from there!
To trigger the memory trim event, an app can be used that fills all the RAM of the device, and that triggers the event.
There are many on the Play Store, they can be found by searching for 'fill ram'.

Make Bluetooth on Android 2.1 discoverable indefinitely

I'm working on a research project which involves Bluetooth and the Android OS. I need to make Bluetooth discoverable indefinitely in order for the project to continue.
The Problem:
Android limits discoverability to 300 seconds.
I cannot ask the user every 300 seconds to turn discoverability back on as my application is designed to run in the background without disturbing the user.
As far as I am aware, there is no way to increase the time though Android's GUI. Some sources have called this a safety feature, others have called this a bug. There may be a bit of truth in both...
What I'm Trying / Have Tried:
I'm trying to edit a stable release of cyanogenmod to turn the discoverability timer off (it's possible; there's a configuration file that needs to have a single number changed). This isn't working because I'm having verification problems with the resulting package.
During the past week, I downloaded the cyanogenmod source code, changed a relevant class in the hope that it would make Bluetooth discoverable indefinitely, and tried to recompile. This did not work because (a) the repo is frequently changed, leading to an unstable code base which fails to compile (OR, it could be that I'm using it incorrectly; just because it looked like it was the code's fault in many instances doesn't mean I should blame it for all the problems I encountered!) and (b) the repo decides to periodically "ignore" me (but not always, as I have gotten the code base before!), replying to my synchronization/connection attempts with:
fatal: The remote end hung up unexpectedly
As you might imagine, the above two issues are problematic and very frustrating to deal with.
More Info:
I'm running Android 2.1 via cyanogenmod (v5 I believe). This means the phone is also rooted.
I have a developer phone, which means that the bootloader is unlocked.
My phone is an HTC Magic (32B).
The Big Question:
How can I make Bluetooth indefinitely discoverable on Android?
See the following link:
http://developer.android.com/guide/topics/wireless/bluetooth.html#ConnectingDevices
Specifically, the last sentence in the paragraph below:
Enabling discoverability
If you would like to make the local device discoverable to other devices, call startActivityForResult(Intent, int) with the ACTION_REQUEST_DISCOVERABLE action Intent. This will issue a request to enable discoverable mode through the system settings (without stopping your application). By default, the device will become discoverable for 120 seconds. You can define a different duration by adding the EXTRA_DISCOVERABLE_DURATION Intent extra. The maximum duration an app can set is 3600 seconds, and a value of 0 means the device is always discoverable.
So, this should work:
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 0);
startActivity(discoverableIntent);
If you check out the BluetoothAdapter class
you will find the hidden method:
public void setDiscoverableTimeout(int timeout)
Now you only have to find out how to use it. You have to do a method invocation to do so.

Categories

Resources