Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

How to Hack Android

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Using public APIs

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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 13

Slide 13 text

–Someone “This is more like session hijacking”

Slide 14

Slide 14 text

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

Slide 15 text

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

Slide 16 text

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 17

Slide 17 text

“Is it practical?”

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

“Is it affordable?”

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

Reflection to access hidden APIs

Slide 22

Slide 22 text

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 23

Slide 23 text

ProGuard • Do not obfuscate statements called via reflection

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26 text

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

Slide 27 text

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

Slide 28 text

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 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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 32

Slide 32 text

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 33

Slide 33 text

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

Slide 34

Slide 34 text

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 35

Slide 35 text

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

Slide 36

Slide 36 text

AIDL to communicate with System services

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

ProGuard • Do not obfuscate auto generated codes and implementation

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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 44

Slide 44 text

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 45

Slide 45 text

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 46

Slide 46 text

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

Slide 47

Slide 47 text

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 48

Slide 48 text

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 49

Slide 49 text

No content

Slide 50

Slide 50 text

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 51

Slide 51 text

No content

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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