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