I'm trying to extend Android's PackageManager functionalities modifying this file:
frameworks/base/services/core/java/com/android/server/pm/SELinuxMMAC.java
When I perform a make clean && make after editing the file and I start the emulator, the changes are there, but this takes too long even with the cache enabled. I tried using mmm framework/base but it does not seem to rebuild the services.core module.
Does anyone know a reliable method to modify a system service and then rebuild efficiently?
mmm and submodules
Create the new classes.dex for the services.core module:
mmm frameworks/base/services/core
Creates the services.jar file including the services.core module that we just rebuilt:
mmm frameworks/base/services
Creates the new system.img for the emulator:
make snod
If the emulator (or the device) is already running, you can use the new services.jar with:
adb remount && adb sync && adb shell stop && adb shell start
In fact mm and mmm do not check for modified submodules, so rebuilding the services module (step 2) without previously rebuilding the services.core (step 1) module is not enough.
DEXPREOPT
If you see the message:
Warning: with dexpreopt enabled, you may need a full rebuild.
You have to turn off the dex preoptimization performing a make clean and then use the following flags in make and mm: WITH_DEXPREOPT=false and DISABLE_DEXPREOPT=true.
Related
In the Android project that I am working on, we are using GitLab CI/CD to automatically build and upload in Diawi the .apk file. In current settings build application's name is static because it needs to be known and sent to the Diawi framework as a curl request. The script looks like this:
- ./gradlew assembleRelease && cp app/build/outputs/apk/release/app-release.apk app-release.apk && curl -v --http1.1 https://upload.diawi.com/ -F token=$DIAWI_TOKEN -F file=#app-release.apk -F find_by_udid=0 -F callback_emails="mymail#company.com"
But this causes some troubles during the manual testing because the .apk files with the same name can be easily mistaken or overwritten.
My idea is to add some metadata in the .apk file's name to be unique and to avoid such errors. Do you have any ideas about how this could be done?
First thing you can do is create version bump functionality. You can do it via version bumping tool and git sync.
For version bumping you can use our open source tool - https://github.com/relizaio/versioning . Now, assuming that you sync via a file called apk_version, you first initialize this file with the current version like:
docker run --rm relizaio/versioning -s YY.0M.Patch > apk_version
Then in your CI context, you can bump it with something like
docker run --rm relizaio/versioning -s YY.0M.Patch -v $(cat apk_version) -a bump > apk_version
Now, in GitLab CI you need to have a block that resolves this. Note, that you also need to commit apk_version file at the end of the bump.
For inspiration - see this question How to grant permission for semantic-release to push code to master and also our sample CD project on GitLab - https://gitlab.com/taleodor/sample-helm-cd/-/blob/master/.gitlab-ci.yml
Also my article here may be helpful (note it's a bit outdated at this point): https://worklifenotes.com/2020/02/27/automatic-version-increments-with-reliza-hub-2-strategies/
Finally, for other things that you can add to version GitLab has a list of pre-defined env variables that you can use in whole or partially as modifiers: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
i modify /framework/base/services/core/java/com/android/server/am/ActivityManagerService.java some logcat output string.
and i try to use different ways to rebuild it:
make -jN from top folder or
mmm /framework/base -jN or
mmm /framework/base/services -jN
and then i get a new output file in /out/target/product/generic_x86/system/framework/x86/services.odex
and then i update system.img by make snod
then i try to restart emulator, or adb remount adb sync, or kill system_server process
but sadly, no matter what kinds of methods i use, the emulator always output the original string.(so angry)
i even extract the new output system.img to get the new services.odex file, and use oat2dex.jar to decompile it to java code, and i indeed see the string has changed in it.
so why when i run the emulator, it won't become effective...
The system image file used by the emulator is system-qemu.img.
For some reason that file isn't made by make snod, which only makes system.img. I think what is needed is an additional target so you could say make qsnod or something, but there doesn't seem to be one. I don't know how anyone can work like this.
I don't understand the Makefile structure well enough at this point to figure out how to add a qsnod target, but here's a way to hand-roll
system-qemu.img.
Notice that the very last step that make -nN reports is:
[100% 255/255] Create system-qemu.img
To find out what command it ran there, you can say make showcommands -jN. I did this, and found it was the following, on my Macbook Pro:
[100% 255/255] /bin/bash -c "(export SGDISK=out/host/darwin-x86/bin/sgdisk; device/generic/goldfish/tools/mk_qemu_image.sh out/target/product/generic_x86_64/system.img)"
So that's the command for making system-qemu.img from input system.img (which is what make snod makes).
So, my recipe for rebuilding system.img on my machine, after changing a .java file under framework/base, is:
mmm frameworks/base -jN
make snod -jN
SGDISK=out/host/darwin-x86/bin/sgdisk device/generic/goldfish/tools/mk_qemu_image.sh out/target/product/generic_x86_64/system.img
Then when I restart the emulator, I see that my change has taken effect.
I have just built Libgit2 (v0.20.0) for Android (target SDK version 18, debugging on a rooted device running Cyanogenmod 10.1.2, Android 4.2.2) and a simple function like getting the version number of Libgit2 works fine through the JNI. But when I use the git_clone function it stops right after the objects/info folder is created and returns this error:
Error -1 cloning repository - Failed to set permissions on '/storage/sdcard0/it/ptt/.git/objects/info': Operation not permitted
I have given the application the WRITE_EXTERNAL_STORAGE permission but I guess it still can't chmod unless owner of the file. When I use adb shell to check out the permission mode of the info folder I get:
d---rwxr-x system sdcard_rw 2014-05-15 09:31 info
And by using pwd.h functions I get the username that the c code (that is calling git_clone) is under to be u0_a92. How am I suppose to get pass this I suppose very Android related issue? Is there a simple way to stop Libgit2 from calling p_chmod or can I give it permissions to do so?
I ended up defining p_chmod as a method always returning true to get passed the error. In the bash script I use to build libgit2 I inserted the following lines that leaves the source files in an unmodified condition after building for android:
LIBGIT2_POSIX_PATH="$LIBGIT2_SOURCE_PATH/src/posix.h"
LIBGIT2_POSIX_BACKUP_PATH="$LIBGIT2_SOURCE_PATH/src/posix_original.h"
printf "#include \"always_success.h\"\nint always_success() { return 0; }" > "$LIBGIT2_SOURCE_PATH/src/always_success.c"
printf "int always_success();" > "$LIBGIT2_SOURCE_PATH/src/always_success.h"
cp $LIBGIT2_POSIX_PATH "$LIBGIT2_POSIX_BACKUP_PATH"
sed -i "s/^#define\sp_chmod(p, m).*$/#include \"always_success.h\"\n#define p_chmod(p, m) always_success()\nextern int always_success();\n/" $LIBGIT2_POSIX_PATH
# run the build process with cmake ...
# restore chmod manipulated source header
mv $LIBGIT2_POSIX_BACKUP_PATH $LIBGIT2_POSIX_PATH
There is probably a cleaner way to solve this but at least now I dont get that error anymore. Thanks to Carlos for his help!
UPDATE
Running adb shell mount | grep sdcard I could see that the sdcard which I am trying to clone the repository into uses the vfat file system which according to this forum thread doesn't support unix-style permissions.
I have a small TV box device running Android. Whenever I bring up the Wi-Fi interface, the Ethernet interface is disconnected. If I then bring up the Ethernet device, the Wi-Fi interface.
I have tried various methods including using the command line to manually bring up the interfaces and the same issue occurs.
I want to be able to connect to the Wi-Fi and have it as my default gateway but then also be connected to the Ethernet port to route certain traffic over that interface.
Obviously this is possible to do in Linux so there must be a way... does anybody know what it is that is tearing down the interfaces when the other is initiated...
This is a restriction in Android. It purposely only allows one connection to be up at a time and has a handler in the 'ConnectivityServices.java' file that tears down a 'non-preferred' network when a network with a priority is enabled. This is also what brings wifi up and tears down cellular data connections when in range of a recognised hotspot...
Just in case anybody ever needs this, here is what I did :
Download the AOSP source code for the version of Android on the device.
Edit the 'ConnectivityServices.java' file accordingly. I basically just commented out the command in the failover command in the connection change handler. I don't have the source code in front of me so message me if you need to know what I did here...
Anyway, then build the AOSP source code on your machine.
Once completed, grab the 'services.jar' file in the /dexclasses/ directory that has been created.
Extract it using WinRAR then copy the 'classes.dex' file out of the .jar file to a separate directory.
Use this to extract the classes.dex : https://code.google.com/p/smali/
Grab the 'ConnectivityServices.smali' file and keep it safe.
From the device
Go onto the device you wish to enable both network interfaces on and copy the /system/framework/services.jar file to a PC. Extract it using WinRAR then copy the 'classes.dex' file out of the .jar file to a separate directory.
Use the Java Smali command to extract the classes.dex.
Take the ConnectivityServices.smali file from the AOSP and put it in the directly you have just extracted using the classes.dex on the device. Might be a good idea to make a backup of the original ConnectivityServices.smali file before overwriting it.
Then simple repackage the classes.dex file using the baksmali command.
Copy the classes.dex file into the original services.jar file using winRAR. Again, take a backup of the original but then overwrite it in the .jar file.
Then simply put the new services.jar file back on the device in the /system/framework/ directory.
Then reboot - it will take longer than normal to boot up on the first time.
There is a simpler way, which doesn't require you to build AOSP matching your device. You can simply modify smali-decompiled code and recompile it. Use https://github.com/android/platform_frameworks_base/blob/master/services/java/com/android/server/ConnectivityService.java for comparizon.
Something along this lines:
adb pull /system/framework/services.jar
cp services.jar services.jar.bak
unzip services.jar classes.dex
java -jar baksmali.jar classes.dex
Edit out/com/android/server/ConnectivityService.smali in handleConnect(), so that this will be the result:
// if this is a default net and other default is running
// kill the one not preferred
if (false && mNetConfigs[newNetType].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) { ...
I made the following change:
aget-object v5, v5, v1
invoke-virtual {v5}, Landroid/net/NetworkConfig;->isDefault()Z
move-result v5
#if-eqz v5, :cond_a6 # changed to unconditional jump
goto :cond_a6
Recompile, repack, push. Then reboot and test.
java -jar smali.jar -o classes.dex out
zip services.jar classes.dex
adb push services.jar /system/framework/services.jar
So I also found out how to do it on CM12.1
Just change this line over here
https://github.com/CyanogenMod/android_frameworks_base/blob/e49d5ea0858a765c22d8aa96cc660d4708a413fb/services/core/java/com/android/server/ConnectivityService.java#L4264
or in smali replace the line before .line 4266
with goto :cond_1b1
Hi I need to copy/move the contents of data/tombstones to sdcard/tombstones
I'm using the command below:
mv data/tombstones /sdcard/tombstones
"failed on 'tombstones' - Cross-device link"
but I'm getting above error.
You have a SANE VERSION of the mv command
paraphrasing a few bits from lbcoder from xda and darkxuser from androidforums
"failed on 'tombstones' - Cross-device link"
It means that you can't create a hard link on one device (filesystem) that refers to a file on a different filesystem.
This is an age-old unix thing. You can NOT move a file across a filesystem using most implementations of mv. mv is not made to copy data from device to device, it simply changes a file's location within a partition. Since /data and /sdcard are different partitions, it's failing.
Consider yourself fortunate that you have a SANE VERSION of the mv command that doesn't try anyway -- some old versions will actually TRY to do this, which will result in a hard link that points to NOTHING, and the original data being INACCESSIBLE.
The mv command does NOT MOVE THE DATA!!! It moves the HARDLINK TO
THE DATA.
If you want to move the file to a different filesystem, you need to use the "cp" command. Copy the file to create a SECOND COPY of it on a different filesystem, and then DELETE the OLD one with the "rm" command.
A simple move command:
#!/bin/bash
dd if="$1" of="$2"
rm -f "$1"
You will note that the "cp" command returns true or false depending on the successful completion of the copy, therefore the original will only be removed IF the file copied successfully.
OR
#!/bin/bash
cat data/tombstones > sdcard/tombstones
rm data/tombstones
These script can be copied into some place referenced by the PATH variable and set executable.
Different Interface
If you need a different interface from adb you may move files using the FileExplorer in DDMS View.
Side note:
You can move a file into a folder when:
You're root;
It is your app directory;
You've used chmod from adb or elsewhere to change permissions
Basically you don't have permission to access /data/tombstones in a production version .
It seems we have to 'root' the device first.
But I failed to root my Samsung S4 which is using Android 4.3