Overview
I execute the command: adb shell cmd package compile -m speed -f my-package
immediately returned Success.
Next, I determine success with the following command.
adb shell dumpsys package my-package
The relevant result is as follows.
Dexopt state:
[my-package]
path: /data/app/~~RlA_7phUWI_QeKL5Ez0VaQ==/my-package-8Q64dwzm_qioAdSVBF3J5g==/base.apk
arm64: [status=speed-profile] [reason=bg-dexopt]
odex file size: base.art: 4712Kb base.odex: 6408Kb base.vdex: 82542Kb
The above information shows that [status=speed-profile] [reason=bg-dexopt] did not work.
My cell phone information
Basic Information:
adb Version: 33.0.2-8557947
Android version: 12
Kernel version: 5.10.66
Whether to root: No
System Properties:
# Note: Only useful information is listed
$ adb shell getprop
[dalvik.vm.usejit]: [true]
[dalvik.vm.usejitprofiles]: [true]
[pm.dexopt.ab-ota]: [speed-profile]
[pm.dexopt.bg-dexopt]: [speed-profile]
[pm.dexopt.boot-after-ota]: [verify]
[pm.dexopt.cmdline]: [verify]
[pm.dexopt.first-boot]: [verify]
[pm.dexopt.first-use]: [speed-profile]
[pm.dexopt.inactive]: [verify]
[pm.dexopt.install]: [speed-profile]
[pm.dexopt.install-bulk]: [speed-profile]
[pm.dexopt.install-bulk-downgraded]: [verify]
[pm.dexopt.install-bulk-secondary]: [verify]
[pm.dexopt.install-bulk-secondary-downgraded]: [extract]
[pm.dexopt.install-fast]: [skip]
[pm.dexopt.post-boot]: [extract]
[pm.dexopt.shared]: [speed]
My Discovery Process
The following logs were obtained via logcat.
PackageManager: Skipped dexOpt for start by shell: my-package
Looking at the Android code, the compilation process returns PackageDexOptimizer.DEX_OPT_SKIPPED
In the DexOptHelper class, there is the following code.
/*package*/ boolean performDexOpt(DexoptOptions options) {
final Computer snapshot = mPm.snapshotComputer();
if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) {
return false;
} else if (snapshot.isInstantApp(options.getPackageName(), UserHandle.getCallingUserId())) {
return false;
}
if (options.isDexoptOnlySecondaryDex()) {
return mPm.getDexManager().dexoptSecondaryDex(options);
} else {
int dexoptStatus = performDexOptWithStatus(options);
return dexoptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
}
}
As you can see, the non-SecondaryDex case is considered successful as long as the result is not PackageDexOptimizer.DEX_OPT_FAILED.
My Questions
Question 1: Why did the adb shell cmd package compile command return Success but did not take effect?
My answer. Referring to the log message above, it was ignored and processed by the system
Question 2: I compile a random package that does not exist, but it also returns Success. e.g. adb shell cmd package compile -m speed -f not-found-package
Same answer as question 1
Question 3: Why is dexOpt not allowed to run in the shell?
Additional Information
Related codes
https://github.com/aosp-mirror/platform_frameworks_base/blob/master/services/core/java/com/android/server/pm/PackageManagerShellCommand.java#L1771
Logs
Adjust the logging level to verbose inside the developer mode.
The following logs are obtained via logcat.
PackageManager: Skipped dexOpt for start by shell: my-package
Related
I am trying to connect two devices to my pc and run some commands on them using python and adb.
when I run the command from the command prompt, it goes through fine, but when i put those in the python script, they give me errors.
this is causing the errors all the time:
from subprocess import check_output, CalledProcessError
try:
adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
print adb_ouput
except CalledProcessError as e:
print e
The error message I get is this:
Usage: adb devices [-l]
Command '['adb', 'devices', '-l', '|', 'grep', '"model"']' returned non-zero exit status 1
When I try the same code without the grep command, it works
adb_ouput = check_output(["adb","devices","-l"])
It gives me the right output.
When I try the same in windows command prompt, It works fine (I am replacing grep with FINDSTR because i'm using it in windows, and I have tried doing the same in the python script as well, with 'shell = True' and also without.)
eg:
adb devices -l | FINDSTR "model"
This gives me an ouptut without any problems.
The output I get is
123ab6ef device product:xxxxxxxxx model:xxxxxxxxx device:xxxxxxxxx
bd00051a4 device product:yyyyyyyyyy model:yyyyyyyyyy device:yyyyyyyyy
I am trying to understand where I am going wrong here, but can't figure it out.
So far I have checked the docs: https://docs.python.org/3/library/subprocess.html
https://docs.python.org/3/library/subprocess.html#subprocess.CalledProcessError
These just give me the error codes.
I have also looked at these answers:
Python, adb and shell execution query
I took some error checking from here and added to my code.
Python subprocess.check_output(args) fails, while args executed via Windows command line work OK
python check_output fails with exit status 1 but Popen works for same command
I think i am close but just can't put my finger on it.
Any help would be appreciated.
First
adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
certainly requires shell=True, but even with that it's not equivalent to
adb devices -l | FINDSTR "model"
When using check_output, you're passing "model" as grep argument literally but you should pass just model. "model" is not in your output (with quotes) so grep fails to find it, and returns exitcode 1 which is not really an error for grep but makes check_output trigger an exception because it expects 0.
So I would to this as a quickfix:
adb_ouput = check_output(["adb","devices","-l","|", "grep", "model"],shell=True)
And as a longfix I'd perform the grep command directly with python.
adb_output = check_output(["adb","devices","-l"])
for l in adb_output.splitlines():
if "model" in l:
print(l)
I am working on one project requires obtaining the complete app package name inside kernel mode. I realized the package name is also the process name inside kernel. However, the task_struct->comm (process name) can only give me 15 characters long.
Also, fs/proc/base.c proc_get_cmdline() can return the full process name but it is private function. I try to export proc_get_cmdline() to public and invoke from my loadable kernel module, but it always crash when I invoke the public proc_get_cmdline().
Is there any way I can get the complete package name inside kernel? Like read from proc/pid/cmdline, read from mm_struct, etc. Appreciate any code example.
You are not supposed to call proc_pid_cmdline().
It is a non-public function in fs/proc/base.c:
static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
However, what it does is simple:
get_cmdline(task, m->buf, PAGE_SIZE);
That is not likely to return the full path though and it will not be possible to determine the full path in every case. The arg[0] value may be overwritten, the file could be deleted or moved, etc. A process may exec() in a way which obscures the original command line, and all kinds of other maladies.
A scan of my opensuse 12.3 system /proc/*/cmdline turns up all kinds of less-than-useful results:
/proc/1/cmdline
/sbin/init showopts
/proc/10/cmdline
/proc/11/cmdline
/proc/1163/cmdline
/sbin/dhclient6 -6 -cf /var/lib/dhcp6/dhclient6.eth0.conf -lf /var/lib/dhcp6/dhclient6.eth0.lease -pf /var/run/dhclient6.eth0.pid -q eth0
/proc/12/cmdline
/proc/13/cmdline
/proc/14/cmdline
/proc/15/cmdline
/proc/16/cmdline
/proc/17/cmdline
/proc/1710/cmdline
/sbin/dhcpcd --netconfig -L -E -HHH -c /etc/sysconfig/network/scripts/dhcpcd-hook -t 0 -h del1-dhp-32429 eth0
/proc/172/cmdline
/proc/185/cmdline
/proc/186/cmdline
/proc/187/cmdline
/proc/19/cmdline
/proc/2/cmdline
/proc/20/cmdline
/proc/21/cmdline
/proc/22/cmdline
/proc/23/cmdline
/proc/25/cmdline
/proc/254/cmdline
/proc/255/cmdline
/proc/26/cmdline
/proc/2671/cmdline
/usr/lib/upower/upowerd
/proc/2674/cmdline
/usr/lib/polkit-1/polkitd --no-debug
/proc/27/cmdline
/proc/2727/cmdline
/usr/lib/udisks2/udisksd --no-debug
/proc/28/cmdline
/proc/285/cmdline
/usr/lib/systemd/systemd-journald
/proc/286/cmdline
/proc/288/cmdline
/proc/29/cmdline
/proc/2913/cmdline
/usr/sbin/cron -n
/proc/2924/cmdline
/usr/sbin/sshd -D
/proc/3/cmdline
/proc/3023/cmdline
/usr/lib/postfix/master
/proc/3090/cmdline
pickup -l -t fifo -u
/proc/3091/cmdline
qmgr -l -t fifo -u
/proc/31/cmdline
/proc/311/cmdline
/usr/lib/systemd/systemd-udevd
/proc/3132/cmdline
/usr/lib/vmware/bin/vmware-vmblock-fuse -o subtype=vmware-vmblock,default_permissions,allow_other /var/run/vmblock-fuse
/proc/3168/cmdline
/usr/sbin/vmware-authdlauncher
/proc/32/cmdline
Works for me in openSUSE 12.3:
for I in /proc/*/cmdline; do echo $I; cat $I | tr '\000' ' '; echo; done
I am writing a ruby script in which I want to execute the android logcat -v time command in a child process and after some time kill the process (when the the parent is done doing xyz).
For example I have:
childpid = Process.fork {
adb -s <device-serial> logcat -c
adb -s <device-serial> logcat -v time>/path-to-file/forkLog.log
}
sleep(30)
#parent do thing else here ...
Process.kill("SIGHUP", childpid) #kill the child process
According to what I've read the adb logcat code is executed in another child sup-process, so when I try to do a Process.kill the childpid stops but its sub-process does not.
how do I kill the logcat -v time>forklog.log process from the parent process??
Typically, when you're using fork to call a bash script, you'll want to use Kernel::exec() instead of Kernel::system() or Kernel::`
Process.fork{exec('adb -s <device-serial> logcat -c && adb -s <device-serial> logcat -v time>/path-to-file/forkLog.log'}
The difference is that exec will replace the Ruby process with the shell script, while the other two will create a subprocess.
We have an android device and as part of testing I need to excute a console test application on the target device. If the test application detects an error it returns -1.
I can use adb shell to run the test applications remotely on the target but I can't find a way of getting back the return code. I need this so I that I can build this into an automated test suite.
I could try grepping the console output for some failure text but that is a bit grubby. Does anyone know of a more elegant solution?
This is a workaround to get the exit code:
adb shell '{your command here} > /dev/null 2>&1; echo $?'
This is a wrapper around adb in Ruby:
def adb(opt)
input = "#{adb_command} #{opt[:command]} #{opt[:params]}"
puts "Executing #{input}...\n"
output = nil
exit_code = 0
def wait_for(secs)
if secs
begin
Timeout::timeout(secs) { yield }
rescue
print 'execution expired'
end
else
yield
end
end
wait_for(opt[:timeout]) do
case opt[:command]
when :install, :push, :uninstall
output, exit_code = `#{input}`, $?.to_i
when :shell
input = "#{adb_command} shell \"#{opt[:params]}; echo \\$?\""
output = `#{input}`.split("\n")
exit_code = output.pop.to_i
output = output.join("\n")
else
raise 'Error: param command to adb not defined!'
end
end
return if opt[:ignore_fail] and output =~ /#{opt[:ignore_fail]}/
raise output unless exit_code == 0
end
You could use Facebook's fb-adb, a "A better shell for Android devices" which "propagates program exit status instead of always exiting with status 0".
I am trying to get the output of a WLAN driver control interface via adb shell on a motorola droid 2. The command is called wlan_cu. To run the command,I am using:
% wlan_cu -itiwlan0 -s /data/jay/stat.sh
Connection established with supplicant .../Connection> Bssid_list,
Connect, Disassociate, Status, Full_bssid_list, wPs/
Status : DISCONNECT MAC : f8.7b.7a.7b.b7.9b SSID : <empty>
BSSID : 00.00.00.00.00.00
Channel : <empty>
Driver/, Connection/, Management/, Show/, Privacy/, scAn/, roaminG/, qOs/, poWer/, eVents/, Bt coexsistance/, Report/, dEbug/, biT/, aboUt, Quit
[1] Segmentation fault wlan_cu -itiwlan0 -s /data/jay/stat.sh
The -s option is to read wlan_cu commands from a script.
% cat /data/jay/stat.sh
c s
/
q
If I try to redirect the output i.e.
% wlan_cu -itiwlan0 -s /data/jay/stat.sh &> out.txt
out.txt is created, but empty and the output still goes to screen. Anyone have an idea? been stuck on this for quite a while.
you can try to redirect both stdout and stderr to the out.txt. Try this,
# wlan_cu -itiwlan0 -s /data/jay/stat.sh > out.txt 2>&1