android emulator restarts itself (ADT) - android

When i invoke a function which is described below, android emulator restarts from beginning.
The function is like that
int index = 0;
Position myPostion;
Position destPosition = roadInstruction.getInstructionAt(index).getEndAddr();
while(index<roadInstruction.getNumInstruction())
{
myPostion = getMyPosition();
while(!hasArrivedToDestination(myPostion, destPosition ))
{
myPostion = getMyPosition();
}
++index;
}
What is the reason?
It maybe because of the inner while loop, but i am not sure.

Related

Digital persona SDK - native problems

I am using in my app Digital Persona SDK for fingerprint identification.
When i use the identify function on less then 250 fmds it works fine.
Engine.Candidate candidates[] = m_engine.Identify(searchedFmd, 0, fmdArray, DEFAULT_THRESHOLD, 1); //fmdArray < 250
But with fmdArray > 250 it gives me a native runtime error:
A/art: art/runtime/indirect_reference_table.cc:132] JNI ERROR (app bug): local reference table overflow (max=512)
Now i runned this app on couple of android devices and came to conclusion that my app crushes with fmdArray > 250 when its running on android 7. But android 8 works fine. In 8 i can preform a check on even 4000 fmds and it works fine.
But i need to run this code in a specific device, that running android 7.
I tried to run it in couple of threads of 250 fmds only. But after single run there is another problem with the SDK. On the second run it doesnt works.
This is what i do:
First i get a fingerprint capture that i want to identify:
Reader.CaptureResult capture = m_reader.Capture(fidFormat, UrUSDK.DefaultImageProcessing, m_DPI, timeout);
// In second run, code after this line is not executed.
// My guees its not coming back from native. No exeptions. No errors.
...
Fmd scannedFmd = m_engine.CreateFmd(capture.image, fmdFormat);
...
int index = identifyFinger(fmds, scannedFmd);
...
private int identifyFinger(List<Fmd> fmdSearchArray, Fmd scannedFmd) {
List<List<Fmd>> lists = splitToChunks(fmdSearchArray);
AtomicInteger index = new AtomicInteger(-1);
List<Callable<Void>> threads = new ArrayList<>(lists.size());
AtomicInteger iteratorIndex = new AtomicInteger(0);
for (int i = 0; i < lists.size(); i++) {
int currentChunk = i;
Callable<Void> thread = () -> {
System.out.println(Thread.currentThread().getName() + " with chunk: " + iteratorIndex.getAndIncrement());
Fmd[] fmds = lists.get(currentChunk).toArray(new Fmd[IDENTIFY_BOUNDARY]);
try {
Engine.Candidate[] candidates = m_engine.Identify(scannedFmd, 0, fmds, threshold, 1);
if (candidates.length > 0) {
index.set(candidates[0].fmd_index + (currentChunk * IDENTIFY_BOUNDARY));
}
} catch (UareUException e) {
}
System.out.println(Thread.currentThread().getName() + " with chunk: " + currentChunk + " finished!");
return null;
};
threads.add(thread);
}
try {
List<Future<Void>> futures = executorService.invokeAll(threads);
System.out.println("All threads finished: " + index.get());
return index.get();
} catch (InterruptedException e) {
e.printStackTrace();
return -1;
}
}
...
private List<List<Fmd>> splitToChunks(List<Fmd> fmdSearchArray) {
int size = fmdSearchArray.size();
List<List<Fmd>> lists;
if (size > IDENTIFY_BOUNDARY) {
int chunks = size / IDENTIFY_BOUNDARY;
if (size % IDENTIFY_BOUNDARY > 0) {
chunks++;
}
lists = new ArrayList<>(chunks);
for (int i = 0; i < chunks; i++) {
if (i + 1 == chunks) {
lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, size)));
break;
}
lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, (i + 1) * IDENTIFY_BOUNDARY)));
}
} else {
lists = new ArrayList<>(1);
lists.add(fmdSearchArray);
}
return lists;
}
The problem with this code is that it runs once. But at another try it doesnt come back from the native code of Caprture call.
So my question is:
How i can overcome this and make it work from my java code?
Or at least what is the direction of the solution?
The root cause is that this Identify function holds on to at least two references per returned Candidate after pushing it to the result array. It should instead release the references after pushing, so its use of the (limited) local reference table remain constant. You should file a bug about that.
The simplest workaround for now is to cut your fmdArray into 250-sized chunks and call Identify for each chunk.

PresetReverb doesn't work at all why?

im a testing my audiorecording application for android
im launching an application to be audio recording in real time with audio effects as below
it was applied to equalizer, bass boost, presetreverb API which developer.android provides
in the result, as for equalizer and bass boost effects they seem to work well, but presetreverb effect.. i don't know why because there was no error in Logcat..
presetreverb don't work at all, i'd like to see it though it even work bad..
so im begging you SOF experts' help
Q: could you find out its cause through my source code?
protected void onResume() {
super.onResume();
if (this.mainSwitch.isChecked()) {
this.audioForwarder.start();
}
this.visualizer.setEnabled(true);
boolean flag = this.eqSwitch.isChecked();
ViewGroup localViewGroup = this.eqSettings;
int i;
int j;
PresetReverb localPresetReverb;
localPresetReverb = this.reverb;
if (flag)
i = 0; // .setVisibility(0) -> View.VISIBLE
else
i = 8; // .setVisibility(8) -> View.GONE
localViewGroup.setVisibility(i); // .setVisibility(0) -> View.VISIBLE
this.equalizer.setEnabled(flag);
this.bassBoost.setEnabled(this.bassSwitch.isChecked());
j = this.reverbSpinner.getSelectedItemPosition();
if (j > 0) {
i = 8;
for (boolean flag1 = true;; flag1 = false) {
localPresetReverb.setEnabled(flag1);
if (this.reverb != null) {
this.reverb.setPreset((short) j);
}
Log.v("PresetReverb", this.reverb + "effect");
}
}
}
im trying on and on expecting your help
any idea appreciated and big helps for me
:)

How to close an Android app using UiAutomator?

How can I close an especific Android app using UiAutomator API?
Like when you manually press the Recents button and swipe the app you want to close.
Better way (not device, OS version, UI or orientation specific):
Runtime.getRuntime().exec(new String[] {"am", "force-stop", "pkg.name.of.your.app"});
Tested and working on a Nexus 5X with android 6.0
The best option would be to use getUiDevice.pressRecentApps, this will load up the recent apps for you, then take a screenshot using the uiautomator viewerso you have a view of the xml of the screen that has been loaded. You can then use this xml to select the object you wish to swipe using
UiObject app = new UIObject(new UiSelector().resourceId("The id of the app");
app.swipeLeft(100);
or right
This should be able to close your app. The xml will depend on what style of android you are using and the device.
This is how I kill all android apps at once with uiautomator:
public static void killApps()
{
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
try
{
device.pressHome();
device.pressRecentApps();
// Clear all isn't always visible unless you scroll all apps down
int height = device.getDisplayHeight();
int width = device.getDisplayWidth();
device.swipe(width/2,height/2, width/2, height, 50);
UiObject clear = device.findObject(new UiSelector()
.resourceId("com.android.systemui:id/button")
.text("CLEAR ALL")
);
if (clear.exists())
{
clear.click();
}
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (UiObjectNotFoundException e)
{
e.printStackTrace();
}
}
Building on the solution from #user597159 I got the following to close all applications on a Pixel 2 for Firebase Test Lab (i.e. the "walleye" device type):
private void killAllApps() throws Exception {
boolean keepSwiping = true;
int maxSwipeAttempts = 10;
uiDevice.pressRecentApps();
for (int swipeAttempt=0; swipeAttempt<maxSwipeAttempts && keepSwiping; swipeAttempt++) {
int height = uiDevice.getDisplayHeight();
int width = uiDevice.getDisplayWidth();
uiDevice.swipe(width / 2, height / 2, width, height / 2, 50);
UiObject clearAll1 = uiDevice.findObject(new UiSelector().text("Clear all"));
UiObject clearAll2 = uiDevice.findObject(new UiSelector().textStartsWith("Clear all"));
UiObject clearAll3 = uiDevice.findObject(new UiSelector().textContains("Clear all"));
UiObject clear = clearAll1.exists() ? clearAll1 :
(clearAll2.exists() ? clearAll2 : clearAll3);
if (clear.exists()) {
Logger.debug(TAG, "Attempting to close app by killAllApps and found clear=all button on swipeAttempt=" + swipeAttempt);
clear.click();
keepSwiping = false;
} else {
Logger.debug(TAG, "Attempting to close app by killAllApps but have to keep swiping swipeAttempt=" + swipeAttempt);
keepSwiping = true;
}
}
}
Note on the Pixel 2, it is spelled "Clear all" not "CLEAR ALL".
I could not get some of the other solutions to work. I got UiObjectNotFoundException for the following:
app = uiDevice.findObject(new UiSelector().textContains("SDK Test App"));
And also for:
app = uiDevice.findObject(new UiSelector().className(com.locuslabs.android.sdk.SdkTestApplication.class));
In other words app.exists() returned false for these approaches that attempted to swipe up on the app to close on Pixel 2.
When it is just one app that will be in the recent app list, this worked for me.
if(mDevice.pressRecentApps()) {
Thread.sleep(1000);
int startX = 300; int startY =835; int endX = 1000; int endY = 835; // co-ordinates refer to x-axis from left of screen to right.
int steps = 8;// speed at which the app closes
mDevice.swipe(startX,startY,endX,endY,steps);
}
Here's a Kotlin answer that is similar to this answer. It adds an extension function to UiDevice to clear all tasks. I tested this on a Pixel 2 emulator.
fun UiDevice.clearAllTasks(swipeAttempts: Int = 10 ) {
pressRecentApps()
var currentAttempt = 1
val centerScreenX = displayWidth / 2
val centerScreenY = displayHeight / 2
while (currentAttempt <= swipeAttempts) {
Timber.d("Clear all tasks attempt $currentAttempt")
swipe(centerScreenX, centerScreenY, displayWidth, centerScreenY, 50)
val uiObject = findObject(UiSelector().text("Clear all"))
if (uiObject.exists()) {
uiObject.click()
break
} else {
currentAttempt++
}
}
}
So I took a little more comprehensive approach to this at it seemed quite unreliable with others answers. I use A LOT of custom extensions so will try to post most of them:
fun UiDevice.clearTasks(swipes: Int = 2) {
logInfo { message("clearTasks swipes:$swipes") }
pressHome()
wait()
pressRecentApps()
wait()
repeat(swipes) {
if (context.isPortrait)
swipe(centerScreenX, centerScreenY, centerScreenX, 50, 10)
else
swipe(centerScreenX, centerScreenY, 25, centerScreenY, 10)
wait()
}
}
fun UiDevice.wait(seconds: Int = defaultWaitTime) {
logInfo { message("wait:$seconds") }
waitForWindowUpdate(null, seconds * SecondLong)
waitForMoreIdle()
}
fun UiDevice.waitForMoreIdle(times: Int = 3) {
logInfo { message("waitForMoreIdle times:$times") }
repeat(times) { waitForIdle() }
}
val UiDevice.centerScreenX get() = displayWidth / 2
val UiDevice.centerScreenY get() = displayHeight / 2
val Context.isPortrait get() = resources.configuration.orientation == ORIENTATION_PORTRAIT
val context: Context get() = ApplicationProvider.getApplicationContext()
Note: I don't really on some text as it depends on language on phone that can be different. Also I like more this custom swipe times approach as I know how much tasks approximately I need to clear out most of the time. There is side effect of showing app launcher but who cares. Didn't find a way to detect it to cancel swiping yet.

coco2d-x call function with multiple arguments?

I'm working on a cocos2d-x project and got stuck. I want to call a function, delay and than call the same function again. I'm using cocos2d-x 2.2.5. and developing for Android.
This is what I got so far:
CCArray *arr = CCArray::create();
arr->addObject(pSprite);
arr->addObject(pGetal);
CCFiniteTimeAction *fun1 = CCCallFuncO::create(this, callfuncO_selector(GameLayer::animateFlip), arr);
CCDelayTime *delay = CCDelayTime::create(1.0);
pSprite->runAction(CCSequence::create(fun1, delay, fun1, NULL));
The method I want to call:
void GameLayer::animateFlip(CCObject *pSObj, CCObject *pGObj){
CCSprite *pSprite = (CCSprite *) pSObj;
CCLabelTTF *pGetal = (CCLabelTTF *) pSObj;
...
...
}
The function is in the same class and requires two arguments. I've tried putting both arguments (CCSprite and CCLabelTTF) in an array, but it crashes on runtime...
When I call the function just like this no errors occur:
this->animateFlip(sprite1, getal1);
Anyone any idea?
Thanks for your answers, I've created a struct for my buttons like Joachim suggested, which has the sprite and the label in it. All the buttons are put in an array. I also added the functions animateFlip and showFlip to it. AnimateFlip works fine and I'm able to call the function from the gamelayer for each indevidial button.
void GameLayer::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent)
{
CCTouch *touch = (CCTouch *)pTouches->anyObject();
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
for(int i = 0; i < 12; i++){
if(butArr[i].sprite->boundingBox().containsPoint(location)){
butArr[i].animateFlip();
break;
}
}
}
The struct:
struct Button
{
cocos2d::CCSprite *sprite;
cocos2d::CCLabelTTF *getal;
int getalINT;
void showFlip();
void animateFlip();
};
But as rule number one in programming tells us, where one problem is solved, two shall arise, I've stumbled upon a new problem:
void Button::showFlip()
{
CCFiniteTimeAction *fun1 = CCCallFunc::create(this, callfunc_selector(Button::animateFlip));
CCFiniteTimeAction *fun1 = CCCallFunc::create(this, callfunc_selector(Button::animateFlip));
CCDelayTime *delay = CCDelayTime::create(1.0f);
this->runAction(CCSequence::create(fun1, delay, fun2, NULL));
}
The CCCallFunc::create() request a context (I guess?), which is usually 'this', but 'this' in my struct point to Button. How can I get the context of the gamelayer?
Thanks again!

throwIndexOutOfBoundsException in updateOomAdjLocked()

In my tests I see the following exception in updateOomAdjLocked() of ActivityManagerService:
// java.lang.IndexOutOfBoundsException: Invalid index 27, size is 27
// at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
// at java.util.ArrayList.get(ArrayList.java:304)
// at com.android.server.am.ActivityManagerService.updateOomAdjLocked(ActivityManagerService.java:13880)
// at com.android.server.am.ActivityManagerService.updateLruProcessLocked(ActivityManagerService.java:1904)
// at com.android.server.am.ActivityStack.realStartActivityLocked(ActivityStack.java:647)
// at com.android.server.am.ActivityStack.startSpecificActivityLocked(ActivityStack.java:803)
Problematic code seems is the following (line 13850 for Android 4.2.2 r1.2):
final ArrayList<ProcessRecord> mLruProcesses
= new ArrayList<ProcessRecord>();
{...}
final void updateOomAdjLocked() {
{...}
final int N = mLruProcesses.size();
for (i=0; i<N; i++) {
ProcessRecord app = mLruProcesses.get(i);
{...}
}
If mLruProcesses.remove was called while in the loop, then mLruProcesses.get(i) for i=N accessed a non-existing index, triggering an exception.
I know very little about Android services so far, so my question is if this code needs to be reenterable, perhaps by making some of the operations thread-safe?
You could verify that the size of mLruProcess.size() is still equal to N within your loop.
final boolean updateOomAdjLocked() {
{...}
final int N = mLruProcess.size();
for(int i = 0; i < N; i++) {
if(N != mLruProcess.size()) {
//Do something accordingly, in this case return false
return false;
}
ProcessRecord app = mLruProcess.get(i);
{...}
}
{...}
return true;
}
Add some logic where you call this function, if it returns false try to have it call the function again. Otherwise, you could put mLruProcess in a Synchronized block which means that it can be accessed in only one concurrent thread. The Synchronized keyword is blocking, which means any code that tries to access mLruProcess in another thread will be blocked until the current thread is done with mLruProcess.
If you don't like to, or can't use blocking code, try using an AtomicBoolean as shown here:
When to use synchronized in Java
Set the AtomicBoolean whenever you change the object stored in mLruProcess and then check that AtomicBoolean everywhere you need to access the objects stored in mLruProcess.

Categories

Resources