Upload
augustine-harvey
View
226
Download
0
Tags:
Embed Size (px)
Citation preview
1
Mobile Software Development Framework: Android IPC; Mobile Push
Notification
10/16/2012
Y. Richard Yang
2
Outline
Admin Android Inter-process communications Mobile push notification
3
Admin.
Schedule for the rest of semester
Recap: Event Handler Execution
4
Event handler (EH) executed by the main/UI thread’s Looper
Slow EH blocks event processing
Guidelines Notify user Incremental
update Short/non-
blocking handler, real processing offloaded to other thread
UI events
systemevents
message
message
message
Looper UI (main) thread
Recap: Background/UI Contention
5
public class LoadingScreen extends Activity implements Runnable {
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.loading);
// start a new thread to load Thread thread = new Thread(this); thread.start(); }
public void run(){ longRunningTask(); setContentView(R.layout.main); }
…}
Conflict with UI thread
Recap: Android Handler
6
Background thread sends msg through handler to UI thread, who processes the msg
Recap: Fixing LoadingScreen
7
Conflict with UI thread
Conflict with UI thread
Conflict with UI thread
8
Recap: Inter-Process Communications (IPC)
Objective: reuse existing data and services among Android components
9
Recap: Inter-Process Communications (IPC)
Component Activity
Component Service
ComponentBroadcastReceiver
startActivity()
startActivityForResult()
startService()
bindService()
broadcastIntent()
Recap: Intent Data Structure Primary pieces of info in an Intent
Action: The general action to be performed• ACTION_VIEW, ACTION_DIAL, ACTION_EDIT, …• Your own definition of strings
Data: a URI• tel:123• content://contacts/people/1• http://zoo.cs.yale.edu/classes/cs434• hotel://name/Omni_New_Haven
Other attributes Category Type (MIME type) Component (class name) Extras (key-value store)
10
scheme
host path
Explicit Intent
11
YelpMapApp
class: MapActivity
To: MapActivity.class
Only the specified activity receives this message
http://developer.android.com/training/basics/firstapp/starting-activity.html
Declare Activity in Manifest
12
Make sure AndroidManifest.xml announces activities that can be started
<application android:icon="@drawable/icon” android:label="@string/app_name" > <activity android:name=".IntentController” android:label="IntentController" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<activity android:name=".TipCal" android:label="TipCal" > </activity>
Shown in Launcher
Announce class
See IntentController
Intent Resolution: Explicit Intent
13
class name
Context
start activity
StartActivity for Result: Caller
14
StartActivity for Result: Called
15
public class CoolGameA extends Activity { private TextView tv2; int previousScore, score; String user; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game); tv2 = (TextView) findViewById(R.id.game_text); //Get the intent that started this activity to fetch passed info Intent i = getIntent(); //returns [] if not initialized by calling activity user = i.getStringExtra("userName"); //returns -1 if not initialized by calling activity previousScore = i.getIntExtra("userScore", -1); tv2.setText(user + ":" + previousScore);
doSessionWithInput(user, previousScore);
StartActivity for Result: Callee
16
//change values for an example of return score = previousScore - 41; //setup button listener Button startButton = (Button) findViewById(R.id.end_game); startButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { //return information to calling activity Intent i = getIntent(); i.putExtra("returnScore", score); i.putExtra("returnName", user); setResult(RESULT_OK, i); finish(); } }); }}
StartActivity for Result: Caller
17
Explicit Intent: Start Service
18
public class PlayMusicService extends Service {
public void onCreate() { super.onCreate(); }
public int onStartCommand(Intent intent, int flags, int startId) { play_music(); return 1; }
private void play_music() { while (true) {
play_music_note(currentIndex);currentIndex++;
} } // end of play_music
http://developer.android.com/guide/components/services.html
Discussion
Problem of explicit intent
19
20
Outline
Admin Android Inter-process communications
Intent data structure Explicit intent Implicit intent
Intent Resolution: Implicit Intent
Intent does not specify exact class to run Info in the Intent used by the system to
determine the best component, at run time, to handle the intent
21
Implicit Intents
22
Yelp
BrowserA
Handles Action: VIEW
Implicit IntentAction: VIEW
Implicit Intents
23
Yelp
BrowserB
BrowserA
Handles Action: VIEW
Handles Action: VIEW
Implicit IntentAction: VIEW
Intent Filter Problem: how to know what an Activity/Service can
handle? Solution: Activities/Services/Receivers declare what they
can/want to receive in Intent filter
24
action
category
data
http://developer.android.com/guide/topics/intents/intents-filters.html
Intent Filter: Example
AndroidManifest.xml file for com.android.browser
25
String action = "android.intent.action.VIEW";Uri data = Uri.parse("http://www.google.com");Intent myIntent = new Intent(action, data);startActivity(myIntent);
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <scheme android:name="http" /> <scheme android:name="https" /> <scheme android:name="file" /></intent-filter>
Implicit Start Activity
26
data
action
See IntentController
A Design Template: Provider
27
<activity android:name=".Booking" android:label=“Booking"> <intent-filter> <action android:name=“com.hotelapp.ACTION_BOOK" /> <data android:scheme=“hotel" android:host=“name”/> </intent-filter></activity>
A Design Template: Provider
28
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
Intent intent = getIntent(); // why am I called String action = intent.getAction(); Uri data = intent.getdata();
String hotelName = data.getPath(); // do the booking
setResult(RESULT_OK); finish();}
A Design Template: Invoker
29
String action = “com.hotelapp.ACTION_BOOK";String hotel = “hotel://name/“ + selectedHotel;Uri data = Uri.parse(hotel);Intent bookingIntent = new Intent(action, data);startActivityForResults(bookingIntent, requestCode);
30
Outline
Admin Android Inter-process communications
Intent data structure Explicit intent Implicit intent Content provider as target of intent
Content Provider
Enable uniformed API for sharing data across applications E.g., Address book, photo gallery
Each provider can expose its data as a simple table on a database model
Query, delete, update, and insert rows31
Content Provider and Intent
Each content provider exposes a public URI that uniquely identifies its data set: android.provider.Contacts.Phones.CONTENT_URI
android.provider.Contacts.Photos.CONTENT_URI android.provider.CallLog.Calls.CONTENT_URI android.provider.Calendar.CONTENT_URI
A content consumer declares access requirement
<uses-permission android:name="android.permission.READ_CONTACTS"/>
32
Content Consumer private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST);}
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // If the request went well (OK) and the request was PICK_CONTACT_REQUEST if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { // Perform a query to the contact's content provider for the contact's name Cursor cursor = getContentResolver().query(data.getData(), new String[] {Contacts.DISPLAY_NAME}, null, null, null); if (cursor.moveToFirst()) { // True if the cursor is not empty int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name = cursor.getString(columnIndex); // Do something with the selected contact's name... } }} 33
34
Outline
Admin Android Inter-process communications
Intent data structure Explicit intent Implicit intent Content provider as target of intent Broadcast intent
Broadcast Intents
Multiple components may be interested in an event/update e.g., system event such as an incoming phone
call, battery level low, network cell changes receives notification by declaring a broadcast
receiver
35
Intent and Broadcast: Sender
String action = "edu.yale.cs434.RUN";
Intent cs434BroadcastIntent = new Intent(action);
cs434BroadcastIntent.putExtra("message", "Wake up.");
sendBroadcast(cs434BroadcastIntent);
36
Example: IntentController
Intent and Broadcast: Receiver<uses-permission android:name="android.permission.READ_PHONE_STAT”>
<receiver android:name="MyPhoneReceiver”>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE”>
</action>
</intent-filter>
</receiver>
<receiver android:name=".CS434BroadcastReceiver" android:enabled="true">
<intent-filter>
<action android:name="edu.yale.cs434.RUN" />
</intent-filter>
</receiver>
37
Intent, Broadcast, Receiver, Notificationpublic class CS434BroadcastReceiver extends BroadcastReceiver {
public static final String CUSTOM_INTENT = "edu.yale.cs434.RUN";
// Display an alert that we've received a message.
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(CUSTOM_INTENT)) {
String message = (String)intent.getExtras().get("message");
CharSequence text = "Got intent " + CUSTOM_INTENT + " with " + message;
int duration = Toast.LENGTH_SHORT;
Toast mToast = Toast.makeText(context, text, duration);
mToast.show();
} // end of if
} // end of onReceive
}
38
Intent, Broadcast, Receiver, Notificationpublic class MyPhoneReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "Incoming number: "+phoneNumber, Toast.LENGTH_LONG).show();
} // end of if
} // end of if
} // end of onReceive
}
39
Discussion: Downside of Implicit Intent
40
Real Example App: iMDb
41
Example App
42
ShowtimeSearch
Results UI
IMDb App
Handles Actions: willUpdateShowtimes,
showtimesNoLocationError
Implicit IntentAction:
willUpdateShowtimes
43
Vulnerability: Eavedropping
ShowtimeSearch
Malicious Receiver
IMDb App
Handles Action: willUpdateShowtimes,
showtimesNoLocationError
Implicit IntentAction:
willUpdateShowtimes
Eavesdropping App
Sending Implicit Intents makes communication public
44
Vulnerability: Spoofing
Malicious Component
Results UI
IMDb App
Handles Action: willUpdateShowtimes,
showtimesNoLocationError
Action: showtimesNoLocationError
Malicious Injection
App
Receiving Implicit Intents makes the component public
45
Vulnerability: Man-in-the-Middle
ShowtimeSearch
Results UI
IMDb App
Handles Action: willUpdateShowtimes,showtimesNoLocation
Error
Malicious Receiver
Handles Action: willUpdateShowtimes,
showtimesNoLocationError
Man-in-the-Middle App
Action: willUpdateShowtimes
Action: showtimesNoLocation
Error
46
Vulnerability: Spoofing
47
Vulnerability: Permission re-Delegation
Permission re-delegation occurs when an application without a permission gains additional privileges through another application
48
Permission System
API
Malware
Deputy
toggleWifi()
Permission System
toggleWifi()
49
Permission Redelegation
Malware
API
Deputy
Malware
toggleWifi()
pressButton(0)
Permission System
Permission Redelegation: Reality Check
50
Analyzed manifests of 5 system applications
Built attacks using 5 of the 16 system apps
Found 15 attacks in the 5 applications
More Examples of Attack
DeskClock: Start an internal service Tell it to infinitely vibrate with a WAKE_LOCK
on
Phone: Trigger the “phone call answered” message
receiver Phone call will be silenced, vibrate cancelled
More details see schedule page links51
More Info on IPC
Intent is a high level abstraction
For more details on implementation of Intent, see a set of slides on binder
52
Binder
AIDL
Intent More abstract
Progress So Far
Issue (responsiveness): slow UI is a sin Solution: event listener gives tasks to
background thread(s) Issue: Background threads may need to
update UI Solution: Handler/AsyncTask so that one
thread can delegate tasks to to another thread
Issue (composability): reusability is highly desired Solution: Intent
53
Problem: Accessing Data in Cloud
A typical setting is that a device accesses data in the cloud
Challenge: How do you keep data on a device fresh?
54
Solution 1: Polling
Simple to implement
Device periodically asks server for new data/update
Appropriate for content that changes constantly Stock Quotes, News Headlines
Problems?55
Impact of Polling on Battery
Baseline: ~5-8 mA Network: ~180-200 mA
Tx more expensive than Rx Assume radio stays on for 10 sec.
Energy per poll: ~0.50 mAh 5 min frequency: ~144 mAh / day
Droid 2 total battery: 1400 mAh
56Source: Android development team at Google
Solution 2: Push Notification
Design issue: Who to push to client device?
Option 1: each app does it individually
Option 2: a shared push service
57
Push Service
A single persistent connection from device to Cloud provider
Multiple application providers push to a cloud provider
Cloud provider pushes to a device using the persistent connection
Two examples Apple Push Notification Service (APNS) Google Cloud Messaging (GCM)
58
Design Issues of a Push Service How to do authorization?
Do not want to allow arbitrary app to push to a device
What to push? Option 1: Just push signal (data available) and
then app fetches from app server or push data
Option 2: push real data
59
Apple Push Notification Service
60
iOS device maintains a persistent TCP connection to a Apple Push Notification Server(APNS)
A push notification from a provider to a client application
Multi-providers to multiple devices
Apple Push Notification: Device Token
61
Device token is analogous to a phone number Contains information that enables APNs to locate the device Client app needs to provide the token to its provider Device token should be requested and passed to providers every time your
application launches
Apple Push Notification Data
Each push notification carries a payload 256 bytes maximum Best effort delivery
App provider provides a JSON dictionary object, which contains another dictionary identified by the key aps
aps specifies the following actions• An alert message to display to the user• A number to badge the application icon with• A sound to play
62
APNS Example: Client
63
1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
2. {3. // Let the device know we want to receive push notifications4. [[UIApplication sharedApplication] registerForRemoteNotificationTypes:5. (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound
| UIRemoteNotificationTypeAlert)];6. 7. return YES;8. }
9. - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
10. {//userInfo contains the notification11. NSLog(@"Received notification: %@", userInfo);12. }
13. - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
14. {15. NSLog(@"My token is: %@", deviceToken);16. }
APNS Example: Server
64
1. $devicetoken ='f05571e4be60a4e11524d76e4366862128f430522fb470c46fc6810fffb07af7’;2. // Put your private key's passphrase here:3. $passphrase = 'PushChat';4. // Put your alert message here:5. $message = ’CS434: my first push notification!';
1. $ctx = stream_context_create();2. Stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');3. stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
4. // Open a connection to the APNS server5. $fp = stream_socket_client(6. 'ssl://gateway.sandbox.push.apple.com:2195', $err,7. $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
8. if (!$fp)9. exit("Failed to connect: $err $errstr" . PHP_EOL);
10. echo 'Connected to APNS' . PHP_EOL;
APNS Example: Server (cont’)
65
16. // Create the payload body17. $body['aps'] = array(18. 'alert' => $message,19. 'sound' => 'default'20. );
21. // Encode the payload as JSON22. $payload = json_encode($body);
23. // Build the binary notification24. $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
25. // Send it to the server26. $result = fwrite($fp, $msg, strlen($msg));
27. if (!$result)28. echo 'Message not delivered' . PHP_EOL;29. else30. echo 'Message successfully delivered' . PHP_EOL;
31. // Close the connection to the server32. fclose($fp);
Google Cloud Messaging
Very similar to APNS
66
GCM Servers
See http://developer.android.com/guide/google/gcm/gs.htmlfor detailed steps
GCM Flow
Enabling cloud to device messaging App (on device) registers with Google, gets
registration ID App sends registration ID to its App Server
Per message App Server sends (authenticated) message to
Google Google sends message to device, which sends to
registered app Disabling cloud to device messaging
App can unregister ID, e.g., when user no longer wants push
67
GCM Flow Enabling cloud to device messaging
App (on device) registers with Google, gets registration ID
68
http://developer.android.com/guide/google/gcm/gs.html
GCM Flow
Enabling cloud to device messaging App (on device) registers with Google, gets
registration ID App sends registration ID to its App Server
Per message App Server sends (authenticated) message to
Google Google sends message to device
Disabling cloud to device messaging App can unregister ID, e.g., when user no
longer wants push69
Android Code: Registration to C2DM// Use the Intent API to get a registration ID
// Registration ID is compartmentalized per app/device
Intent regIntent = new
Intent(“com.google.android.c2dm.intent.REGISTER”);
// Identify your app
regIntent.putExtra(“app”,
PendingIntent.getBroadcast(this, 0, new Intent(), 0);
// Identify role account server will use to send
regIntent.putExtra(“sender”, emailOfSender);
// Start the registration process
startService(regIntent);
70
Receiving Registration ID
71
// Registration ID received via an Intent
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (“…REGISTRATION”.equals(action)) {
handleRegistration(context, intent);
} }
private void handleRegistration(Context context, Intent intent){
String id = intent.getExtra(“registration_id”);
if ((intent.getExtra(“error”) != null) {
// Registration failed. Try again later, with backoff.
} else if (id != null) {
// Send the registration ID to the app’s server.
// Be sure to do this in a separate thread.
} }
Receiving Registration ID
App receives the ID as an Intent com.google.android.c2dm.intent.REGISTRATIO
N App should send this ID to its server Service may issue new registration ID at
any time App will receive REGISTRATION Intent
broadcast App must update server with new ID
72