last day (15 days later) » 

1:58 PM
Hey, do you happen to know something about Linux shell commands?
I have this command that works 4 out of 5 times, but 1 time it gives an error.
Android.
 
I can probably answer anything about the shell.
 
> cat /proc/$(pidof $( dumpsys window windows | awk '/mCurrentFocus/ {
sub(/\/.*/,""); print $3}' ))/status | awk '/Uid:/ {print $2}'
 
Gorsh. :)
 
The command. It gets the UID from the active application.
 
Understood.
 
2:00 PM
When it doesn't work, it seems to be ignoring the part between proc/ and /status.
> tmp-mksh: <stdin>[2]: cat: /proc//status: No such file or directory
If this some performance issue?
 
cat /proc/$(
   pidof $(
      dumpsys window windows
    | awk '/mCurrentFocus/ {
         sub(/\/.*/,""); print $3
       }'
))/status | awk '/Uid:/ {print $2}'
@Cerberus No. Race condition of some sort, perhaps.
 
Is that equivalent?
 
What I typed? Yes: I merely added whitespace for legibility.
 
@tchrist That means some part is finished before it should, or something?
 
Yes.
 
2:01 PM
@tchrist OK I thought so.
OK.
The person who wrote that deliberately put it all in one line in order to improve the speed. Do you think that makes sense?
 
It’s a rather elaborate way to figure this out. Surprised there is no better method.
@Cerberus Zero.
 
Hmmm.
 
Why would it improve speed to be all on one line?
 
He said he had measured that starting the shell itself took the most time in Android on his phone.
Whereas the command(s) it/themselves were milliseconds.
 
Well, he’s calling the shell at least three times there.
Each $(..) being a subshell.
 
2:04 PM
And a subshell is no faster than a new shell? If I'm phrasing that correctly.
 
Well, it may be just as slow. I’ve seen systems where starting a shell is slow.
I don't know the "pidof" of "dumpsys" commands, as those are likely some Android-specific thing and not general Unix stuff, but that’s not really material here.
I know nothing about the Android kernel, but it may make soft real-time guarantees of some sort, or not run a normal context-switcher.
 
Right, that seems likely.
> Bob, you were 100% correct. The majority of time is taken up by android to startup the shell. In my case it takes ~1005 milliseconds to run an empty shell and just additional 4-7 milliseconds to execute the statements.
 
And if it does, that would impact start-up.
It probably doesn’t matter which is the first command run: it will always be slowest due to some latency involved in starting up a new process of this sort.
 
OK.
Do you think splitting it into several lines could make the whole thing more reliable?
I suspect that on my phone it is fast enough anyway.
 
It would make it more readable and therefore more maintainable. It would not impact speed.
 
2:08 PM
Nor would it impact reliability?
 
Correct.
 
I see.
But, if I split it up, I could perhaps diagnose the problem better by checking for error messages per line?
 
What it’s really trying to do is cat out a file name /proc/SOMEPID/status, right?
 
I think so...
 
The timing issue is that all the files in /proc are "magic".
 
2:10 PM
Its sole purpose is to give the PID of the active application.
 
They are figments, models that exist only so long as that process is alive.
 
I read about that...
 
But I can’t see why the active process would go away.
So I begin to question all his awking regexes.
 
The strange thing is that the problem does not disappear if I add a 3-second wait (after the application has opened) before the shell executes.
 
That double-slash error message you showed means that sometimes the first awk finds nothing in the output of dumpsys that matches /mCurrentFocus/.
 
2:12 PM
Hmm but the same application that resulted in an error will work perfectly the next time.
 
It may be that the output of that command is volatile or inconsistent with the expectation that it always contain that string.
 
I see.
 
Technically, it could be either of pidof or dumpsys which has that property.
 
So perhaps I should save the output in a log file, along with any error messages, to analyse it.
OK.
 
Yes, very good idea.
Do you know how to tee off a clone of your stdout en route?
Instead of "| cmd |" write instead "| cmd | tee -a somelogfile |"
 
2:14 PM
I don't even know what that means, but I use Tasker, which has ways to save the error message.
 
That will append a copy of the output produced by cmd into the named file while continuing to pass along what it found to the next pipeline phase as though nothing had gotten in the way.
 
@tchrist Okay, and that would save any errors to a log file?
OK.
 
It would save the original output, not the errors.
 
Ah OK.
 
I think we want to know what sort of output dumpsys is creating.
 
2:15 PM
But I can save the errors anyway.
Does it append rather than replace the log file?
@tchrist Haha OK, half of all this is abracadabra to me.
 
@Cerberus I told you I could probably answer any shell question. I didn’t promise that you would understand my answer. :)
 
@tchrist pidof is a standard sysvinit tool. No idea about the other one.
 
@terdon Oh. Well, you know I go to the other church. :)
 
:)
 
@tchrist Je sais, je sais.
This is funny.
Hmm do you have any idea how I should go about spliting the command? Is there a standard / automatic way to do that?
 
2:23 PM
What do you mean by splitting the command?
 
Probably not...
Well, splitting the thingy I posted into several thingies that I can have post error messages?
I suppose I could first add the thangy you posted between wherever I see pipes...
@tchrist Different in what way?
 
Syntactically.
Plus you had some other way to do that, you said.
 
@tchrist Ah, okay. I do have another method, but that only happens at the end of the whole thingy.
@tchrist It already does that, which is how I came up with the original error message.
 
2:39 PM
@Cerberus Unix questions are better asked in U&L.
 
They are, but terdon and I are both here, and he knows us.
 
Ah, I seem to have found something.
> mCurrentFocus=null
 
The chat room is usually not very active, but as long as you don't appear brain damaged, you'll probably get an answer.
 
Yup.
That’s it.
 
@tchrist Fair enough.
 
2:40 PM
This is in the output of the thingy command.
So Android thinks the application is not in focus. How can it think nothing is in focus?
 
Because people have returned to the main screen not an application screen? Dunno.
 
But it is I who did it.
I simply opened Google Maps, at which point the command executes automatically.
 
And you have an application screen that you can see running at the time?
Ah.
 
Look, this is also in the dump from that command:
> mFocusedApp=AppWindowToken{447293f0 token=Token{44327a80 ActivityRecord{43c0d478 u0 com.google.android.apps.maps/com.google.android.maps.MapsActivity t18}}}
 
Was that from the same run?
 
2:44 PM
@tchrist The purpose of all this is for Android to automatically allow the location permission whenever I am actually using Google Maps, and restrict it again when the application is no longer in the foreground.
@tchrist Yes.
 
Can’t see how mCurrentFocus=null while mFocusedApp=(not null) at the same time. But it’s Android. Who can guess?
 
Heh.
I don't even know what the difference between them is.
 
Perhaps the person who wrote it’s understanding of dumpsys is incomplete.
 
That seems likely.
 
And yes, that’s a deliberant clitic ’s on the whole phrase, not an ignorant spelling error.
A very rare case of possessive it’s. :)
 
2:46 PM
(I need to know the PID of the foreground application in order to modify Xprivacy's database, so that Xprivacy will give and take the permission automatically.)
@tchrist Makes sense.
 
Android should really provide some /proc/fgpid/ interface.
 
The sentence wouldn't have parsed without the apostrophe.
@tchrist Perhaps it does, but we do not know about it?
 
One never knows, but it would be immediately obvious by running an ls command on /proc.
Hm, or maybe not. It could evaporate.
 
@tchrist Perhaps the reason he chose mCurrentApp because it contains the PID, whereas mFocusedApp does not. But I can convert the com.google.android.apps.maps thingy into the PID with some other command, so perhaps that would be more reliable.
 
Can you?
 
2:49 PM
Yes.
 
Then you’re a better man than I, Gunga Din.
 
I have saved the command to do that somewhere.
I hope...
At least I remember finding it and saving it.
Perhaps it is specific to Android.
 
Quite certainly.
 
> # pidof com.example.poc_service
 
@Cerberus Hm well. That posits that "com.example.poc_service" is the name of the process, I believe. Perhaps it is.
 
2:59 PM
I hope so.
Trying it now.
It doesn't seem to be working...
 
Try adding -x.
 
Where, at the end?
I now see some people are saying pidof is not available on Android by default...
Works at neither position...
Perhaps pidof just doesn't work.
 
Normally options precede arguments.
@Cerberus Ahah!
 
@tchrist OK but that didn't work.
 
Try which pidof
 
3:08 PM
@tchrist OK!...
 
It’s in /sbin/pidof
Which is probably not in your path.
Try ls -l /sbin/pidof
That’s an ell not a one.
 
Odd that it works some of the time though. Unless you've solved that, I was away for a few minutes.
 
No, that’s the odd thing.
 
@terdon Very odd.
 
It wouldn’t work some of the time if there were no pidof command available.
 
3:10 PM
Can you get it to fail on purpose?
 
These are the commands Busybox adds to Androird, including pidof (I have Busybox): busybox.net/downloads/BusyBox.html
 
I'm guessing the format of some of the /proc files is different for specific applications so the awk parsing bit fails.
 
@terdon Yes: sometimes mCurrentApp is "null", even though mActiveApp shows the package name, in the same instance.
 
@Cerberus But is there a specific case where it always fails?
 
@tchrist So what would the whole thing look like? # ls -l /sbin/pidof com.google.android.apps.maps
 
3:13 PM
No.
I just wanted to know if you had a pidof command.
 
@terdon No, with more than one application it fails sometimes.
 
@Cerberus But will it also work on the same application other times?
 
Google Maps and Amazon App Store are the ones where it seemed to fail more often with.
@terdon Yes.
 
Very odd.
 
@Cerberus what is your question? An Android programming question?
 
3:13 PM
Completely unpredictable, except perhaps that heavier applications are less happy.
 
What I would like to see is the contents of a /proc/PID/status file that it chokes on.
 
@FaheemMitha Not exactly.
 
@FaheemMitha Yes, about an Android shell thingy.
 
@terdon He showed some of that.
Well, not exactly. It can't get the PID so there is no status.
 
@Cerberus ok.
 
3:14 PM
> mCurrentFocus=null
mFocusedApp=AppWindowToken{447293f0 token=Token{44327a80 ActivityRecord{43c0d478 u0 com.google.android.apps.maps/com.google.android.maps.MapsActivity t18}}}
 
That’s from this dumpsomething I think.
Or is that part of /proc/SOMEPID/status?
 
This is part of the dumpsys output thingy that caused an error: I need the mCurrentFocus thingy or it won't work.
 
Right.
 
@tchrist It is from dumpsys window windows.
 
He was getting /proc//status errors because the pid interpolated was empty because awk spat out nothing.
 
3:16 PM
Which figures, since mCurrentFocus is "null".
 
Perhaps your phone has ADHD.
 
Could be!
Hey, I see now that the original shell thingy uses pidof, we didn't notice.
So there is no problem with pidof itself.
1 hour ago, by tchrist
cat /proc/$(
   pidof $(
      dumpsys window windows
    | awk '/mCurrentFocus/ {
         sub(/\/.*/,""); print $3
       }'
))/status | awk '/Uid:/ {print $2}'
 
@Cerberus No, the issue is that awk sometimes returns nothing. This will be either because it had blank input or because the format is wrong.
 
@terdon It had blank input, because mCurrentFocus was somehow null.
But why?
On a good day, mCurrentFocus contains the package name, presumably.
 
Well, or process name.
 
3:19 PM
@Cerberus Because either i) no line matched mCurrentFocus or ii) the matching line had no 3rd field or iii) the 3rd field started with a /.
 
@Cerberus Probably best to put a newline after the semicolon and align the print $3 with the previous line.
cat /proc/$(
   pidof $(
      dumpsys window windows
    | awk '/mCurrentFocus/ {
         sub(/\/.*/,"");
         print $3;
       }'
))/status | awk '/Uid:/ {print $2}'
Just makes it slightly clearer is all.
Although you can only go so far. :)
 
@terdon The matching line has this: mCurrentFocus=null
So then awk can't work with that, right?
 
@Cerberus Exactly
 
Look at the regex it’s trying.
There is no slash in the string.
 
Yup
more importantly, there is no $3, the regex is irrelevant.
 
3:22 PM
This is from a good dump:
> mCurrentFocus=Window{44f4c918 u0 net.dinglisch.android.taskerm/net.dinglisch.android.taskerm.MacroEdit}
mFocusedApp=AppWindowToken{45a480b8 token=Token{45a45c30 ActivityRecord{45a45a20 u0 net.dinglisch.android.taskerm/.MacroEdit t35}}}
 
@Cerberus Yes, that will print net.dinglisch.android.taskerm
 
Bad dump:
> mCurrentFocus=null
mFocusedApp=AppWindowToken{447293f0 token=Token{44327a80 ActivityRecord{43c0d478 u0 com.google.android.apps.maps/com.google.android.maps.MapsActivity t18}}}
 
OK, so basically, you can't get the PID of the focused window when there is no focused window. Seems reasonable enough. Now, when isn't there a focused window in android?
 
@tchrist Ok so I can replace it with that?
 
Presumably when you're on the home or notification screens or when switching between apps.
 
3:24 PM
@Cerberus Nothing that will help you.
There just isn’t the data there to start with.
Oh wait.
You could get it from mFocusedApp.
 
Yes, indeed!
Duh!
 
And probably should.
 
@tchrist Yeah that was what I was trying to say...
 
Always.
 
@tchrist Is it better?
 
3:26 PM
It seems to be reliable.
 
@Cerberus try replacing the awk bit with this: awk '/mFocusedApp/{print $(NF-1)}'
Ah no, hang on
 
Heh.
 
@terdon Yes, that is the question. The script auto-executes when I open e.g. Google Maps, so Maps should have focus.
@tchrist Oops never mind.
 
This:
awk '/mFocusedApp/{sub(/\/.*/,"",$(NF-1)); print $(NF-1)}'
So, this:
cat /proc/$(
   pidof $(
      dumpsys window windows
    | awk '/mFocusedApp/{sub(/\/.*/,"",$(NF-1)); print $(NF-1)}'
))/status | awk '/Uid:/ {print $2}'
 
Wowie, thanks. Trying it...
@terdon Wait, my bad.
 
3:31 PM
@Cerberus Ah, yes, sorry, this one then:
 
No, no, it was my bad.
 
cat /proc/$(
   pidof $(
      dumpsys window windows |
     awk '/mFocusedApp/{sub(/\/.*/,"",$(NF-1)); print $(NF-1)}'
))/status | awk '/Uid:/ {print $2}'
 
I forgot to remove all the new lines.
 
Not necessary
 
Really?
 
3:31 PM
Course.
 
Let's see...
(Tom's earlier version where he had simply added new lines resulted in a similar error, I believe, but OK.)
 
@Cerberus Yes, because the | was at the beginning of the line. If it's at the end, it acts as a line break.
Assuming the above works, you can simplify it to this and avoid a useless use of cat:
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | awk '/mFocusedApp/{sub(/\/.*/,"",$(NF-1)); print $(NF-1)}'))
 
And you wonder why people use perl. :)
 
@tchrist I don't!
 
@terdon It works! Now let me test it on some heavy apps...
 
3:34 PM
@Cerberus Yay!
And, if your awk supports it, you could further simplify to:
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}))'
 
Don’t all awks supports regex args to -F?
 
Perhaps, I'm not sure.
Yes, [it seems to be POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html) : "FS
Input field separator regular expression; a <space> by default."
 
> Hey, I had to let awk be better at *something*...
—Larry Wall, Usenet article <1991Nov7.200504.25280@netlabs.com> (1991)
 
@terdon Hmm I just got the original procc//status error again.
 
Referencing the -F bit. :)
 
3:39 PM
Let me add Tom's tee -a thingy back into Terdon's command.
 
@Cerberus Whoah, what tee -a? That will add text to a file.
 
@terdon Sorry, it writes the output of a command to a (log) file.
 
Trying to debug dumpsys.
 
Ah, OK
 
On the failure case.
 
3:40 PM
@Cerberus did you try this one:
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))
 
I was still testing the first one...OK will test this one.
 
@LittleEva We aren’t usually this way here, honest. :)
 
@terdon Syntax error: ( unmatched.
 
@Cerberus Sorry, try again with the edited version.
 
Ok!
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | tee /sdcard/Download/uid.txt | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))
(For easy sending to my phone.)
Cmnd line 1 is a directory
 
3:49 PM
Damn, yes, sorry:
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))/status
 
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | tee /sdcard/Download/uid.txt | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))/status
 
@Cerberus Yeah, that should work.
 
@terdon Hmm now I get the proc//status error again.
 
Grrr. What am I screwing up?
 
Hehe.
 
3:52 PM
Let's go back to the useless cat again. Does this work?
cat /proc/$(pidof $(dumpsys window windows | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))/status | awk '/Uid:/ {print $2}'
 
@terdon Nope, proc//status
If you add the | tee /sdcard/Download/uid.txt | part in every time, I can give you the dump more quickly.
Otherwise I have to paste-and-edit it in every time.
 
OK:
cat /proc/$(pidof $(dumpsys window windows | tee -a /sdcard/Download/uid.txt | awk -F'[ /]' '/mFocusedApp/{print $(NF-1)}'))/status | awk '/Uid:/ {print $2}'
 
Thanks!
@terdon proc//status, alas.
 
@Cerberus OK, what's in the /sdcard/Download/uid.txt file?
 
Sending you a copy...
Can you open this?
Never mind.
But that file is the right one.
Hmm I see the launcher is seen as the "focused app".
 
4:05 PM
AAAAAaaaaaaa!
 
But Maps is the "current focus"
 
cat /proc/$(pidof $(dumpsys window windows | tee -a /sdcard/Download/uid.txt | awk -F'[ /]' '/mFocusedApp/{print $(NF-2)}'))/status | awk '/Uid:/ {print $2}'
 
Haha yay!
proc//status...
 
dammit!
 
4:08 PM
@Cerberus No worries. I tend to enjoy this kind of thing. OK, the issue now is that there are two lines matching mFocusedApp so both are printed.
 
@terdon No, that is because you added -a "append".
That's several dumps in one file.
 
@Cerberus No, they're there in the input:
$ grep mFocusedApp a
mFocusedApp=AppWindowToken{45b318e8 token=Token{44364a30 ActivityRecord{43c835e8 u0 net.dinglisch.android.taskerm/.MacroEdit t61}}}
mFocusedApp=null
I thought that mFocusedApp could never be null.
 
@terdon Those are not from the same instance of the script, I believe.
 
Also, maybe we should take this to a new room so we don't spam everyone here.
 
I run the script a few times until I get the error.
Each time, the dump is appended to the file.
 
4:11 PM
@Cerberus join me here?
 
@terdon Yay!
Did you get what I said about appending several dumps to the same file?
 
Hang on, I'll move those messages here.
 
I believe the problem is that sometimes mCurrentFocus=null, and at other times mFocusedApp=null.
So whichever one you pick, there will come a time when it is null and it fails.
But they never appear to be null at the same time.
 
141 messages moved from English Language & Usage
@Cerberus Ah. That does complicate things. OK, let's make it either/or then. Hang on.
@Cerberus can you show me an example of the output of dumpsys window windows for each case? I mean one where mCurrentFocus=null and one where mFocusedApp is?
 
> mCurrentFocus=Window{43d83388 u0 com.google.android.apps.maps/com.google.android.maps.MapsActivity}
mFocusedApp=null
This is one.
 
4:19 PM
Damn, and the format is different. OK
 
> mCurrentFocus=null
mFocusedApp=AppWindowToken{447293f0 token=Token{44327a80 ActivityRecord{43c0d478 u0 com.google.android.apps.maps/com.google.android.maps.MapsActivity t18}}}
Another.
 
You have busybox, right? So sed should work and might be easier.
 
I do.
 
OK, let me try a few things
 
By the way, I seem to be only getting the error with Google Maps now.
So perhaps mFocusedApps is more stable for other applications.
 
4:25 PM
@terdon That was a lot of work. :)
 
@tchrist Yeah, I realized that half way through selecting all those messages :)
 
Hmm now I get it with Amazon again too.
> mCurrentFocus=Window{442d0f88 u0 com.amazon.venezia/com.amazon.venezia.Venezia}
mFocusedApp=null
 
@terdon Should I move the rest of the messages here?
 
@tchrist That'd be great!
 
k
 
4:30 PM
I figure they don't really belong in the main room
 
@tchrist I'm terribly sorry, but I have to run. I will open chat on my phone, perhaps I can continue to experiment walking...
Oops, that was directed @terdon
 
@Cerberus No worries. I'll post a solution in a few seconds
 
@terdon Woohoo!
By the way, when the two entries are both valid but different, I think mCurrentFocus is better.
 
They should be identical, right?
 
Because, sometimes, Current will be the app and App the launcher.
I remember seeing that in the past.
 
4:37 PM
OK, this should work
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | tee /sdcard/Download/uid.txt | awk '{if(/mCurrentFocus|mFocusedApp/){for(i=1;i<=NF;i++){if(sub(/\/.*/,"",$i)){print $i; exit}}  } }'))/status
2
 
175 messages moved from English Language & Usage
 
@tchrist Cheers
 
Now, why didn't that work?
Weird.
I had a million messages selected and moved them.
Here.
 
@tchrist I think it did.
 
Oh ok.
Usually it leaves a placeholder a million message moved. :)
 
4:40 PM
You might need to reload the tab.
@Cerberus I've pinned the final (I hope) solution.
 
2 messages moved from English Language & Usage
@terdon Oh I see.
I didn't even notice that this was in U&L not ELU.
It had an L and U after all. :)
 
Heh. I figured I'd bring it to a site better suited to the subject matter.
 
5:00 PM
@terdon Thanks! But.... ) syntax error.
( unmatched
 
@Cerberus Again. Sigh, sorry. Try the edited one.
awk '/Uid:/ {print $2}' /proc/$(pidof $(dumpsys window windows | tee /sdcard/Download/uid.txt | awk '{if(/mCurrentFocus|mFocusedApp/){for(i=1;i<=NF;i++){if(sub(/\/.*/,"",$i)){print $i; exit}}  } }'))/status
 
5:38 PM
@terdon It works!!
No errors so far, except the launcher's being identified sometimes.
But that cannot be fixed this way.
But I can work around it with Tasker.
 
@Cerberus Yay! :)
 
As in, if pid=launcher, run script again.
@terdon Thank you very much! I will keep testing it.
 
@Cerberus Do you know how to set that up or do you need help with it?
 
@terdon I think I can do it, I have some experience with Tasker.
Do you?
 
@Cerberus No. I would have done it in the shell. If you can do it with tasker, go for it.
 
5:46 PM
I may have to ask for your help again with regards to getting the pid from the package name.
 
@Cerberus Feel free. Glad I could help.
 
@terdon I just mentioned to my friends here how this great Greek was helping me whose name I don't even know.
 
@Cerberus Heh :) It's Charles. Or Karolos, depending on language.
What's yours, by the way?
 

  last day (15 days later) »