'

Deep Inside Android Hacks

Понравилась презентация – покажи это...





Слайд 0

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


Слайд 1

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


Слайд 2

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


Слайд 3

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


Слайд 4

How to Hack Android


Слайд 5

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


Слайд 6

Using public APIs


Слайд 7

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


Слайд 8

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


Слайд 9

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


Слайд 10

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


Слайд 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


Слайд 12

“This is more like session hijacking” –Someone


Слайд 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()) } }


Слайд 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()) } }


Слайд 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()) } }


Слайд 16

“Is it practical?”


Слайд 17

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


Слайд 18

“Is it affordable?”


Слайд 19

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


Слайд 20

Reflection to access hidden APIs


Слайд 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


Слайд 22

ProGuard • Do not obfuscate statements called via reflection


Слайд 23

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


Слайд 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”); } }


Слайд 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”); } }


Слайд 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”); } }


Слайд 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”); } }


Слайд 28

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


Слайд 29

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


Слайд 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


Слайд 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


Слайд 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


Слайд 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


Слайд 34

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


Слайд 35

AIDL to communicate with System services


Слайд 36

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


Слайд 37

ProGuard • Do not obfuscate auto generated codes and implementation


Слайд 38

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


Слайд 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


Слайд 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


Слайд 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


Слайд 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… }


Слайд 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); }


Слайд 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


Слайд 45

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


Слайд 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); }


Слайд 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) { } }


Слайд 48


Слайд 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


Слайд 50


Слайд 51

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


Слайд 52

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


Слайд 53


×

HTML:





Ссылка: