Deep Inside Android Hacks


The Presentation inside:

Slide 0

Deep Inside Android Hacks Keishin Yokomaku (KeithYokoma) @ Drivemode, Inc. Android All Stars #dotsandroid


Slide 1

Profile • Keishin Yokomaku at Drivemode, Inc. • Social: @KeithYokoma • Publication: Android Training • Product: • Like: Bicycle, Photography, Tumblr • Nickname: Qiita Meister


Slide 2

Drivemode • Now available on Play Store! • http://bit.ly/1LYdxAg


Slide 3

E-book • AndroidTraining / iOS Training • http://amzn.to/1mZNydv


Slide 4

How to Hack Android


Slide 5

How to Hack Android • Using public APIs • Reflection to access hidden APIs • AIDL to communicate with System services


Slide 6

Using public APIs


Slide 7

Using public APIs • It’s official! • Less likely to crash coming from customizations


Slide 8

android.media.session • Lollipop API • Components • MediaSession and MediaSession.Token • MediaController • Notification.MediaStyle


Slide 9

MediaSession and MediaController • Permit transport control by session token Media Application Token MediaSession Other Application MediaController Transport Control


Slide 10

NotificationListenerService • Background service listening to status bar notification events NotificationManager Notification notify onNotificationPosted NotificationListenerService


Slide 11

Notification.MediaStyle • Pass MediaSession.Token to system notification • When you listen to notification event… • MediaSession.Token is in `extras` • Key for `extras` is defined on Notification • MediaSession.Token is valid even if the receiver is not intended to


Slide 12

“This is more like session hijacking” –Someone


Slide 13

Take control of music playback public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); } } public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) } }


Slide 14

Take control of music playback public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); } } public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) } }


Slide 15

Take control of music playback public class MusicNotificationWatcher extends NotificationListenerService { private Bus eventBus; @Override public void onNotificationPosted(StatusBarNotification sbn) { MediaSession.Token token = sbn.getNotification().extras.getParcelable(Notification.EXTRA_MEDIA_SESSION); eventBus.post(new NewMusicNotification(token)); } } public class MyActivity extends Activity { private MediaController controller; @Subscribe public void onNewMusicNotificationAdded(NewMusicNotification event) { controller = new MediaController(this, event.getToken()) } }


Slide 16

“Is it practical?”


Slide 17

Is it practical? • It depends • You cannot fully cover overall music experience • For keyguard apps, this is good enough


Slide 18

“Is it affordable?”


Slide 19

Is it affordable? • No • Because it works only on Lollipop and with Google Play Music


Slide 20

Reflection to access hidden APIs


Slide 21

Reflection to access hidden APIs • It’s unofficial, dirty, unpaved… • No IDE support for you • Be careful about ProGuard settings • Breaking changes might be happening under the hood • Performance issue


Slide 22

ProGuard • Do not obfuscate statements called via reflection


Slide 23

Reflection basics • Class • • Method • • Object#getClass(), Class.forName(), Class literal Class#getDeclaredMethods(), Class#getDeclaredMethod() Field • Class#getDeclaredFields(), Class#getDeclaredField()


Slide 24

Example package com.sample; public class Something { private void foo(String str) {} } public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); } }


Slide 25

Example package com.sample; public class Something { private void foo(String str) {} } public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); } }


Slide 26

Example package com.sample; public class Something { private void foo(String str) {} } public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); } }


Slide 27

Example package com.sample; public class Something { private void foo(String str) {} } public class ReflectionSample { public void reflect(Something something) throws Exception { Method foo = something.getDeclaredMethod(“foo”, String.class); foo.setAccessible(true); foo.invoke(something, “bar”); } }


Slide 28

Accessing hidden APIs • Methods / Fields • getDeclared** to get private (or hidden) one • setAccessible(true) to make it visible to us


Slide 29

“Why are you using wrecking reflection?” “Because it is practical”


Slide 30

Practicality of reflection • Aggressive usage • • • to get informations that is generally prohibited for normal apps to use system functions Reluctant usage • to avoid/patch bugs in framework


Slide 31

Aggressive reflection • You can do almost everything • Read `RemoteViews` operations • Read actual `Intent` on `PendingIntent` • Call hidden method to register object onto system service


Slide 32

Karma of aggressive reflection • Spoil encapsulation • • It may not work • • Need to pay attention to the object state No guarantee that every phone has the same method or field Google is watching you


Slide 33

Reluctant reflection • Avoid bugs in framework • Ex. http://bit.ly/1HkJvR4 • • Fix wrong path for preferences files on G***** S Ex. http://bit.ly/1E5kB7L • Backward compatibility


Slide 34

Benefits of reluctant reflection • Reduce a lot of pains on users who are using broken phone • Keep new API available on old phones


Slide 35

AIDL to communicate with System services


Slide 36

AIDL to communicate with System services • Yet another dirty work • Be careful about ProGuard settings


Slide 37

ProGuard • Do not obfuscate auto generated codes and implementation


Slide 38

AIDL basics • Implementing AIDL stub • Put .aidl in `src/main/aidl` • Compile it • Implement stub methods in Java code


Slide 39

A lot of AIDLs in framework • Intent, Bundle, Uri, Bitmap, Rect, Account… • • Data container objects passed to each processes MediaSession, ICameraService, ITelephonyService… • Abstraction of some operations


Slide 40

Media Controller on the Lock Screen • Android 4.0 and above (up to Android 4.2) • RemoteControlClient and IRemoteControlDisplay Media Application RemoteControl Client Publish media state AudioManager Transport Control Lock Screen IRemoteControl Display


Slide 41

Media Controller on the Lock Screen • Android 4.0 and above (up to Android 4.2) • RemoteControlClient and IRemoteControlDisplay Media Application RemoteControl Client Publish media state AudioManager Transport Control Lock Screen IRemoteControl Display


Slide 42

IRemoteControlDisplay // in IRemoteControlDisplay.aidl package android.media; oneway interface IRemoteControlDisplay { // various methods declared… } // in Java code public class RemoteControlDisplay extends IRemoteControlDisplay.Stub { // various implementations here… }


Slide 43

AudioManager private final AudioManager mAudioManager; private final IRemoteControlDisplay mDisplay; public void setUp() throws Exception { Method register = mAudioManager.getClass().getDeclaredMethod( “registerRemoteControlDisplay”, IRemoteControlDisplay.class); register.invoke(mAudioManager, mDisplay); } public void tearDown() throws Exception { Method unregister = mAudioManager.getClass().getDeclaredMethod( “unregisterRemoteControlDisplay”, IRemoteControlDisplay.class); unregister(mAudioManager, mDisplay); }


Slide 44

AIDL Versioning • IRemoteControlDisplay • • • IRemoteControlDisplay is available from ICS New method is added on JB But… • The method name is the same (overloaded) • AIDL does not support overloading


Slide 45

Workaround for method overload • AIDL definition • • Keep the latest Java implementation • Declare every version of overloaded methods


Slide 46

IRemoteControlDisplay // ICS version oneway interface IRemoteControlDisplay { setPlaybackState(int id, int state, long stateChangeTimeMs); } // JB version oneway interface IRemoteControlDisplay { setPlaybackState(int id, int state, long stateChangeTimeMs, long currentPosMs, float speed); }


Slide 47

IRemoteControlDisplay public class RemoteControlDisplay extends IRemoteControlDisplay.Stub { public void setPlaybackState(int id, int state, long stateChangeTimeMs) { } @Override public void setPlaybackState(int id, int state, long stateChangeTimeMs, long currentPosMs, float speed) { } }


Slide 48


Slide 49

Internal AIDL usage • Be aware of method declaration • • If no method found, the app will crash Keep compatible • Define the same signature method on implementation


Slide 50


Slide 51

“Don’t be afraid. Keep calm and happy hacking!”


Slide 52

Deep Inside Android Hacks Keishin Yokomaku (KeithYokoma) @ Drivemode, Inc. Android All Stars


Slide 53


×

HTML:





Ссылка: