SlideShare uma empresa Scribd logo
1 de 49
How to recognise that the user
has just uninstalled your Android
app
fb.me/pjakubczyk
+AleksanderPiotrowski
@pelotasplus
Opera Max
The Java way
Read the broadcast
<receiver android:name=".PackageWatcher">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action
android:name="android.intent.action.PACKAGE_REMOVED"/>
<action
android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
Read the broadcast
void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Iterator<String> it =
bundle.keySet().iterator;
while (it.hasNext()) {
String key = it.next();
Log.e("DDD", key +"="+bundle.get(key)); }
Usually we see (install)
E/DDD (29199): Dumping Intent start
[android.intent.extra.UID=10089]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Usually we see (reinstall)
E/DDD (29199): Dumping Intent start
[android.intent.extra.REMOVED_FOR_ALL_USERS=false]
[android.intent.extra.UID=10089]
[android.intent.extra.DATA_REMOVED=false]
[android.intent.extra.REPLACING=true]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Usually we see (uninstall)
E/DDD (29199): Dumping Intent start
[android.intent.extra.REMOVED_FOR_ALL_USERS=true]
[android.intent.extra.UID=10089]
[android.intent.extra.DATA_REMOVED=true]
[android.intent.extra.user_handle=0]
E/DDD (29199): Dumping Intent end
Let’s uninstall our app
and there’s nothing ….
Why ?
OS unregisters listener during removal
What Opera does?
It does not listen for package removal
it does some magic ;-)
… not in Java code
Getting the APK
Getting the APK
● genymotion with
gapps installed
● get app from play store
● be careful with the right ABI
Getting the APK
1.adb shell
2.pm list packages
Getting the APK
3. pm path com.opera.max
4. adb pull
/data/app/com.opera.max.apk
Hacking APK
Apktool
A tool for reverse engineering
Android apk files
Made with <3 in Poland ;-)
Apktool
Easy to use
$ apktool d
com.opera.max.apk
Apktool
● decoded XML files
● smali assembly code
● PNGs, layouts, resources
● id-s mapping
with Opera Max APK
live apktool demo
Opera Findings
Found a clue!
There are *.so files
We can inspect them to see more
Tools: strings, objdump, nm, readelf
rudy$ strings opera/lib/armeabi/libuo.so (II)
...
inotify_init
inotify_add_watch
inotify_rm_watch
/data/data/%s/
%s%s
inotify framework
http://linux.die.net/man/7/inotify
The inotify API provides a mechanism
for monitoring file system events.
Inotify can be used to monitor individual
files, or to monitor directories.
rudy$ strings opera/lib/armeabi/libuo.so (I)
...
Android
start
android.intent.action.VIEW
--user
...
am command
part of Android system
/system/bin/am
A way to start apps, intents and
whatnot
more details
$ ps
USER PID PPID
u0_a91 24318 20265 246900 27716 ffffffff b6edf5cc S
com.opera.max
u0_a91 24337 24318 856 336 c00e4944 b6f72158 S
/data/app-lib/com.opera.max-2/libuo.so
The scenario
1. Fork the native process
2. Inside the child process use inotify to watch
a file
3. Watcher is woken up on file deletion. Start
another native process
4. The last process run the ‘am’
(ActivityManager) command to run intent.
Setup
JNI
local.properties
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System,
please read the
sdk.dir=/Users/alek/android-sdk
ndk.dir=/Users/alek/android-ndk-r10e
build.gradle
android.defaultConfig {
applicationId "pl.pelotasplus.actionafteruninstall"
ndk {
moduleName "hello-jni"
ldLibs "log", "android"
stl "stlport_static"
}
}
MainActivity.java declaring
public class MainActivity extends AppCompatActivity {
public native String stringFromJNI();
public native void observer();
static {
System.loadLibrary("hello-jni");
// System.loadLibrary("/data/data/com.foo.test/lib/liba.so");
}
}
MainActivity.java calling
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
textView.setText(stringFromJNI());
observer();
}
project structure
Native code
JNI
Sample by Google
jstring
Java_pl_pelotasplus_actionafteruninstall_MainActivity_stringFro
mJNI
(JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(
env,
"Hello from JNI ! Compiled with ABI foo."
);
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDFLAGS += -llog -lpthread
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := armeabi-v7a
# all
APP_STL := stlport_static
inotify on Linux
int main( int argc, char **argv) {
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];
fd = inotify_init();
printf("fd=%dn", fd);
}
inotify on Linux
int main( int argc, char **argv)
{
[...]
wd = inotify_add_watch(fd, "/var/tmp",
IN_MODIFY | IN_CREATE | IN_DELETE);
length = read( fd, buffer, BUF_LEN );
printf("length=%dn", length);
if (length < 0) {
perror("read");
}
inotify on Linux
while (i < length) {
struct inotify_event *event = (struct inotify_event*)&buffer[ i];
printf("Event len %dn", event->len);
if (event->len) {
if (event->mask & IN_DELETE) {
if (event->mask & IN_ISDIR) {
printf( "The directory %s was deleted.n", event->name );
} else {
printf( "The file %s was deleted.n", event->name );
inotify on Android (pseudo code)
void observer(void) {
inotify_init();
inotify_add_watch(fd, DIRECTORY, IN_DELETE);
if (event->mask & IN_DELETE) {
startIntent();
}
}
first attempt
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject
thiz)
{
observer();
}
App blocked as native code blocked app
second attempt, with thread
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer
(JNIEnv* env, jobject thiz)
{
pthread_attr_init(&attr);
pthread_create(&thread, &attr, &observer_thread, NULL);
}
App not blocked but native code stopped when stopping app for
uninstalling
third attempt, with fork
void
Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz)
{
pid_t pid;
pid = fork();
if (pid == 0) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Fork childn");
observer();
}
}
start intent, another fork
void startIntent(void) {
pid_t p = fork();
if (p == 0) {
__android_log_print(ANDROID_LOG_INFO, TAG, "startIntent %d", getpid());
system("/system/bin/am start --user 0 -a
android.intent.action.VIEW -d http://droidcon.de");
}
}
Live demo of our app
https://github.com/
pelotasplus/Action
AfterUninstall
Check the dirty source code
Moral
> What happens when I call fork() in JNI code? Will this totally break the
> Activity lifecycle model in Android?
Don't do this. Just don't.
--
Dianne Hackborn
Android framework engineer
hack...@android.com
http://markmail.org/message/ruqp2t6gvhnhv654

Mais conteúdo relacionado

Mais procurados

Unix Programming with Perl
Unix Programming with PerlUnix Programming with Perl
Unix Programming with Perl
Kazuho Oku
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Robert Nyman
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet
 

Mais procurados (20)

Unix Programming with Perl 2
Unix Programming with Perl 2Unix Programming with Perl 2
Unix Programming with Perl 2
 
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonbСтажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
Стажировка 2016-07-27 02 Денис Нелюбин. PostgreSQL и jsonb
 
Unix Programming with Perl
Unix Programming with PerlUnix Programming with Perl
Unix Programming with Perl
 
Continuous testing In PHP
Continuous testing In PHPContinuous testing In PHP
Continuous testing In PHP
 
Introduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI PotsdamIntroduction to puppet - Hands on Session at HPI Potsdam
Introduction to puppet - Hands on Session at HPI Potsdam
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
 
Intro django
Intro djangoIntro django
Intro django
 
Using the Power to Prove
Using the Power to ProveUsing the Power to Prove
Using the Power to Prove
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
 
Guarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous TestingGuarding Your Code Against Bugs with Continuous Testing
Guarding Your Code Against Bugs with Continuous Testing
 
EC2
EC2EC2
EC2
 
Commencer avec le TDD
Commencer avec le TDDCommencer avec le TDD
Commencer avec le TDD
 
Reactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/O
 
NodeJs
NodeJsNodeJs
NodeJs
 
The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12
 
Debian 5 Hardening Tips
Debian 5 Hardening TipsDebian 5 Hardening Tips
Debian 5 Hardening Tips
 
Docker for data science
Docker for data scienceDocker for data science
Docker for data science
 
Puppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the ForgePuppet Module Reusability - What I Learned from Shipping to the Forge
Puppet Module Reusability - What I Learned from Shipping to the Forge
 
Introduction to JavaFX 2
Introduction to JavaFX 2Introduction to JavaFX 2
Introduction to JavaFX 2
 
General fraction
General fractionGeneral fraction
General fraction
 

Destaque (9)

Uo Inspiration
Uo InspirationUo Inspiration
Uo Inspiration
 
RoboSpock
RoboSpockRoboSpock
RoboSpock
 
lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2lake victoria brotherhood photo alubm presentation 2
lake victoria brotherhood photo alubm presentation 2
 
Robospock droidcon '14
Robospock   droidcon '14Robospock   droidcon '14
Robospock droidcon '14
 
Android accounts & sync
Android accounts & syncAndroid accounts & sync
Android accounts & sync
 
It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016It's always your fault. Poznań ADG 2016
It's always your fault. Poznań ADG 2016
 
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
Récapitulatif de tous les résultats fin 2012des sociétés cotées au 16 Mars 20...
 
Upline daily du 29 02 2012
Upline daily du 29 02 2012Upline daily du 29 02 2012
Upline daily du 29 02 2012
 
Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012Récapitulatif des résultats au 27 mars 2012
Récapitulatif des résultats au 27 mars 2012
 

Semelhante a How to recognise that the user has just uninstalled your android app

Jakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix toolsJakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
DevSecCon
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
Ben Lin
 

Semelhante a How to recognise that the user has just uninstalled your android app (20)

How to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your appHow to recognise that the user has just uninstalled your app
How to recognise that the user has just uninstalled your app
 
Iwatch tech 1
Iwatch tech 1Iwatch tech 1
Iwatch tech 1
 
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHackAn inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
An inconvenient truth: Evading the Ransomware Protection in windows 10 @ LeHack
 
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix toolsJakob Holderbaum - Managing Shared secrets using basic Unix tools
Jakob Holderbaum - Managing Shared secrets using basic Unix tools
 
Uninstall opera
Uninstall operaUninstall opera
Uninstall opera
 
Gdg san diego android 11 meetups what's new in android - ui and dev tools
Gdg san diego android 11 meetups  what's new in android  - ui and dev toolsGdg san diego android 11 meetups  what's new in android  - ui and dev tools
Gdg san diego android 11 meetups what's new in android - ui and dev tools
 
Android
AndroidAndroid
Android
 
Node.js basics
Node.js basicsNode.js basics
Node.js basics
 
test
testtest
test
 
Information track presentation_final
Information track presentation_finalInformation track presentation_final
Information track presentation_final
 
Linux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium SandboxLinux Security APIs and the Chromium Sandbox
Linux Security APIs and the Chromium Sandbox
 
Gimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault AnalysisGimli: Server Process Monitoring and Fault Analysis
Gimli: Server Process Monitoring and Fault Analysis
 
Virus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing GatekeeperVirus Bulletin 2015: Exposing Gatekeeper
Virus Bulletin 2015: Exposing Gatekeeper
 
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentationMacOS forensics and anti-forensics (DC Lviv 2019) presentation
MacOS forensics and anti-forensics (DC Lviv 2019) presentation
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
PHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vulnPHP Backdoor: The rise of the vuln
PHP Backdoor: The rise of the vuln
 
Android dev
Android devAndroid dev
Android dev
 
FRIDA 101 Android
FRIDA 101 AndroidFRIDA 101 Android
FRIDA 101 Android
 
My name is Trinidad
My name is TrinidadMy name is Trinidad
My name is Trinidad
 
Permission enforcement s in android new (1)
Permission   enforcement s  in android new (1)Permission   enforcement s  in android new (1)
Permission enforcement s in android new (1)
 

Último

Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Cara Menggugurkan Kandungan 087776558899
 

Último (6)

BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
 
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
9999266834 Call Girls In Noida Sector 52 (Delhi) Call Girl Service
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
 
Leading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdfLeading Mobile App Development Companies in India (2).pdf
Leading Mobile App Development Companies in India (2).pdf
 
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
Obat Penggugur Kandungan Di Apotik Kimia Farma (087776558899)
 
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
 

How to recognise that the user has just uninstalled your android app

  • 1. How to recognise that the user has just uninstalled your Android app fb.me/pjakubczyk +AleksanderPiotrowski @pelotasplus
  • 3.
  • 5. Read the broadcast <receiver android:name=".PackageWatcher"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <action android:name="android.intent.action.PACKAGE_REPLACED"/> <data android:scheme="package"/> </intent-filter> </receiver>
  • 6. Read the broadcast void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Iterator<String> it = bundle.keySet().iterator; while (it.hasNext()) { String key = it.next(); Log.e("DDD", key +"="+bundle.get(key)); }
  • 7. Usually we see (install) E/DDD (29199): Dumping Intent start [android.intent.extra.UID=10089] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 8. Usually we see (reinstall) E/DDD (29199): Dumping Intent start [android.intent.extra.REMOVED_FOR_ALL_USERS=false] [android.intent.extra.UID=10089] [android.intent.extra.DATA_REMOVED=false] [android.intent.extra.REPLACING=true] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 9. Usually we see (uninstall) E/DDD (29199): Dumping Intent start [android.intent.extra.REMOVED_FOR_ALL_USERS=true] [android.intent.extra.UID=10089] [android.intent.extra.DATA_REMOVED=true] [android.intent.extra.user_handle=0] E/DDD (29199): Dumping Intent end
  • 10. Let’s uninstall our app and there’s nothing …. Why ? OS unregisters listener during removal
  • 11. What Opera does? It does not listen for package removal it does some magic ;-) … not in Java code
  • 13. Getting the APK ● genymotion with gapps installed ● get app from play store ● be careful with the right ABI
  • 14. Getting the APK 1.adb shell 2.pm list packages
  • 15. Getting the APK 3. pm path com.opera.max 4. adb pull /data/app/com.opera.max.apk
  • 17. Apktool A tool for reverse engineering Android apk files Made with <3 in Poland ;-)
  • 18. Apktool Easy to use $ apktool d com.opera.max.apk
  • 19. Apktool ● decoded XML files ● smali assembly code ● PNGs, layouts, resources ● id-s mapping
  • 20. with Opera Max APK live apktool demo
  • 22. Found a clue! There are *.so files We can inspect them to see more Tools: strings, objdump, nm, readelf
  • 23. rudy$ strings opera/lib/armeabi/libuo.so (II) ... inotify_init inotify_add_watch inotify_rm_watch /data/data/%s/ %s%s
  • 24. inotify framework http://linux.die.net/man/7/inotify The inotify API provides a mechanism for monitoring file system events. Inotify can be used to monitor individual files, or to monitor directories.
  • 25. rudy$ strings opera/lib/armeabi/libuo.so (I) ... Android start android.intent.action.VIEW --user ...
  • 26. am command part of Android system /system/bin/am A way to start apps, intents and whatnot
  • 27. more details $ ps USER PID PPID u0_a91 24318 20265 246900 27716 ffffffff b6edf5cc S com.opera.max u0_a91 24337 24318 856 336 c00e4944 b6f72158 S /data/app-lib/com.opera.max-2/libuo.so
  • 28. The scenario 1. Fork the native process 2. Inside the child process use inotify to watch a file 3. Watcher is woken up on file deletion. Start another native process 4. The last process run the ‘am’ (ActivityManager) command to run intent.
  • 30. local.properties # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the sdk.dir=/Users/alek/android-sdk ndk.dir=/Users/alek/android-ndk-r10e
  • 31. build.gradle android.defaultConfig { applicationId "pl.pelotasplus.actionafteruninstall" ndk { moduleName "hello-jni" ldLibs "log", "android" stl "stlport_static" } }
  • 32. MainActivity.java declaring public class MainActivity extends AppCompatActivity { public native String stringFromJNI(); public native void observer(); static { System.loadLibrary("hello-jni"); // System.loadLibrary("/data/data/com.foo.test/lib/liba.so"); } }
  • 33. MainActivity.java calling protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); textView.setText(stringFromJNI()); observer(); }
  • 36. Sample by Google jstring Java_pl_pelotasplus_actionafteruninstall_MainActivity_stringFro mJNI (JNIEnv* env, jobject thiz) { return (*env)->NewStringUTF( env, "Hello from JNI ! Compiled with ABI foo." ); }
  • 37. Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_LDFLAGS += -llog -lpthread include $(BUILD_SHARED_LIBRARY)
  • 38. Application.mk APP_ABI := armeabi-v7a # all APP_STL := stlport_static
  • 39. inotify on Linux int main( int argc, char **argv) { int length, i = 0; int fd; int wd; char buffer[BUF_LEN]; fd = inotify_init(); printf("fd=%dn", fd); }
  • 40. inotify on Linux int main( int argc, char **argv) { [...] wd = inotify_add_watch(fd, "/var/tmp", IN_MODIFY | IN_CREATE | IN_DELETE); length = read( fd, buffer, BUF_LEN ); printf("length=%dn", length); if (length < 0) { perror("read"); }
  • 41. inotify on Linux while (i < length) { struct inotify_event *event = (struct inotify_event*)&buffer[ i]; printf("Event len %dn", event->len); if (event->len) { if (event->mask & IN_DELETE) { if (event->mask & IN_ISDIR) { printf( "The directory %s was deleted.n", event->name ); } else { printf( "The file %s was deleted.n", event->name );
  • 42. inotify on Android (pseudo code) void observer(void) { inotify_init(); inotify_add_watch(fd, DIRECTORY, IN_DELETE); if (event->mask & IN_DELETE) { startIntent(); } }
  • 43. first attempt void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz) { observer(); } App blocked as native code blocked app
  • 44. second attempt, with thread void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer (JNIEnv* env, jobject thiz) { pthread_attr_init(&attr); pthread_create(&thread, &attr, &observer_thread, NULL); } App not blocked but native code stopped when stopping app for uninstalling
  • 45. third attempt, with fork void Java_pl_pelotasplus_actionafteruninstall_MainActivity_observer(JNIEnv* env, jobject thiz) { pid_t pid; pid = fork(); if (pid == 0) { __android_log_print(ANDROID_LOG_INFO, TAG, "Fork childn"); observer(); } }
  • 46. start intent, another fork void startIntent(void) { pid_t p = fork(); if (p == 0) { __android_log_print(ANDROID_LOG_INFO, TAG, "startIntent %d", getpid()); system("/system/bin/am start --user 0 -a android.intent.action.VIEW -d http://droidcon.de"); } }
  • 47. Live demo of our app
  • 49. Moral > What happens when I call fork() in JNI code? Will this totally break the > Activity lifecycle model in Android? Don't do this. Just don't. -- Dianne Hackborn Android framework engineer hack...@android.com http://markmail.org/message/ruqp2t6gvhnhv654