Merge "Auto Messaging API Sample First draft" into lmp-dev
diff --git a/AutoMessagingDemo/.gitignore b/AutoMessagingDemo/.gitignore
new file mode 100644
index 0000000..afbdab3
--- /dev/null
+++ b/AutoMessagingDemo/.gitignore
@@ -0,0 +1,6 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
diff --git a/AutoMessagingDemo/README.txt b/AutoMessagingDemo/README.txt
new file mode 100644
index 0000000..cfd4e6a
--- /dev/null
+++ b/AutoMessagingDemo/README.txt
@@ -0,0 +1,39 @@
+Android Auto Messaging API Sample
+=================================
+
+MessagingService.java shows a simple service that sends notifications using NotificationCompat.
+In addition to sending a notification, it also extends the notification with a CarExtender.
+Each unread conversation from a user is sent as a distinct notification.
+
+CheckList while building a messaging app that supports Android Auto:
+-------------------------------------------------------------------
+1. Add or import the android-auto-sdk.jar into your app.
+2. Ensure that Message notifications are extended using
+NotificationCompat.Builder.extend(new CarExtender()...)
+3. Add meta-data to your AndroidManifest.xml to specify that your app
+is automotive enabled.
+
+       <meta-data android:name="com.google.android.gms.car.application"
+                   android:resource="@xml/automotive_app_desc"/>
+
+and include the following to indicate that the application wants to show notifications on
+the overview screen.
+res/xml/automotive_app_desc.xml
+
+<automotiveApp>
+    <uses name="notification"/>
+</automotiveApp>
+
+Flow
+-----
+MessagingFragment is shown to the user. Depending on the button clicked, the MessagingService is
+sent a message. MessagingService inturn creates notifications which can be viewed either on the
+emulator or in a car.
+When a message is read, the associated PendingIntent is called and MessageReadReceiver is called
+with the appropriate conversationId. Similarly, when a reply is received, the MessageReplyReceiver
+is called with the appropriate conversationId. MessageLogger logs each event and shows them in a
+TextView in MessagingFragment for correlation.
+
+Known Issues:
+-------------
+- Emulator: Reply always sends text "This is a reply". No voice input in emulator.
diff --git a/AutoMessagingDemo/app/.gitignore b/AutoMessagingDemo/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/AutoMessagingDemo/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/AutoMessagingDemo/app/build.gradle b/AutoMessagingDemo/app/build.gradle
new file mode 100644
index 0000000..4e7f2ec
--- /dev/null
+++ b/AutoMessagingDemo/app/build.gradle
@@ -0,0 +1,30 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 21
+    buildToolsVersion "21.0.0"
+
+    defaultConfig {
+        applicationId "com.example.android.automessagingdemo"
+        minSdkVersion 21
+        targetSdkVersion 21
+        versionCode 1
+        versionName "1.0"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+    buildTypes {
+        release {
+            runProguard false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:21.0+'
+}
diff --git a/AutoMessagingDemo/app/libs/android-auto-sdk.jar b/AutoMessagingDemo/app/libs/android-auto-sdk.jar
new file mode 100644
index 0000000..8a9897d
--- /dev/null
+++ b/AutoMessagingDemo/app/libs/android-auto-sdk.jar
Binary files differ
diff --git a/AutoMessagingDemo/app/proguard-rules.pro b/AutoMessagingDemo/app/proguard-rules.pro
new file mode 100644
index 0000000..dc41957
--- /dev/null
+++ b/AutoMessagingDemo/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /usr/local/google/home/nageshs/Software/build-1404642-LRW65B/android-sdk_1404642_linux-x86/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/AutoMessagingDemo/app/src/main/AndroidManifest.xml b/AutoMessagingDemo/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b0b6f60
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/AndroidManifest.xml
@@ -0,0 +1,52 @@
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.automessagingdemo">
+
+    <application android:allowBackup="true"
+        android:label="@string/app_name"
+        android:icon="@drawable/ic_launcher"
+        android:theme="@style/AppTheme">
+
+        <meta-data android:name="com.google.android.gms.car.application"
+                   android:resource="@xml/automotive_app_desc"/>
+
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <service android:name=".MessagingService">
+        </service>
+
+        <receiver android:name=".MessageReadReceiver">
+            <intent-filter>
+                <action android:name="com.example.messaging.messagemedemo.ACTION_MESSAGE_READ"/>
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name=".MessageReplyReceiver">
+            <intent-filter>
+                <action android:name="com.example.messaging.messagemedemo.ACTION_MESSAGE_REPLY"/>
+            </intent-filter>
+        </receiver>
+    </application>
+</manifest>
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/Conversations.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/Conversations.java
new file mode 100644
index 0000000..d92beec
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/Conversations.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * A simple class that denotes unread conversations and messages. In a real world application,
+ * this would be replaced by a content provider that actually gets the unread messages to be
+ * shown to the user.
+ */
+public class Conversations {
+
+    /**
+     * Set of strings used as messages by the sample.
+     */
+    private static final String[] MESSAGES = new String[]{
+            "Are you at home?",
+            "Can you give me a call?",
+            "Hey yt?",
+            "Don't forget to get some milk on your way back home",
+            "Is that project done?",
+            "Did you finish the Messaging app yet?"
+    };
+
+    /**
+     * Senders of the said messages.
+     */
+    private static final String[] PARTICIPANTS = new String[]{
+            "John Rambo",
+            "Han Solo",
+            "Rocky Balboa",
+            "Lara Croft"
+    };
+
+    static class Conversation {
+
+        private final int conversationId;
+
+        private final String participantName;
+
+        /**
+         * A given conversation can have a single or multiple messages.
+         * Note that the messages are sorted from *newest* to *oldest*
+         */
+        private final List<String> messages;
+
+        private final long timestamp;
+
+        public Conversation(int conversationId, String participantName,
+                            List<String> messages) {
+            this.conversationId = conversationId;
+            this.participantName = participantName;
+            this.messages = messages == null ? Collections.<String>emptyList() : messages;
+            this.timestamp = System.currentTimeMillis();
+        }
+
+        public int getConversationId() {
+            return conversationId;
+        }
+
+        public String getParticipantName() {
+            return participantName;
+        }
+
+        public List<String> getMessages() {
+            return messages;
+        }
+
+        public long getTimestamp() {
+            return timestamp;
+        }
+
+        public String toString() {
+            return "[Conversation: conversationId=" + conversationId +
+                    ", participantName=" + participantName +
+                    ", messages=" + messages +
+                    ", timestamp=" + timestamp + "]";
+        }
+    }
+
+    private Conversations() {
+    }
+
+    public static Conversation[] getUnreadConversations(int howManyConversations,
+                                                        int messagesPerConversation) {
+        Conversation[] conversations = new Conversation[howManyConversations];
+        for (int i = 0; i < howManyConversations; i++) {
+            conversations[i] = new Conversation(
+                    ThreadLocalRandom.current().nextInt(),
+                    name(), makeMessages(messagesPerConversation));
+        }
+        return conversations;
+    }
+
+    private static List<String> makeMessages(int messagesPerConversation) {
+        int maxLen = MESSAGES.length;
+        List<String> messages = new ArrayList<>(messagesPerConversation);
+        for (int i = 0; i < messagesPerConversation; i++) {
+            messages.add(MESSAGES[ThreadLocalRandom.current().nextInt(0, maxLen)]);
+        }
+        return messages;
+    }
+
+    private static String name() {
+        return PARTICIPANTS[ThreadLocalRandom.current().nextInt(0, PARTICIPANTS.length)];
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MainActivity.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MainActivity.java
new file mode 100644
index 0000000..7236c2c
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MainActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        if (savedInstanceState == null) {
+            getFragmentManager().beginTransaction()
+                    .add(R.id.container, new MessagingFragment())
+                    .commit();
+        }
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageLogger.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageLogger.java
new file mode 100644
index 0000000..e899a71
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageLogger.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * A simple logger that uses shared preferences to log messages, their reads
+ * and replies. Don't use this in a real world application. This logger is only
+ * used for displaying the messages in the text view.
+ */
+public class MessageLogger {
+
+    private static final String PREF_MESSAGE = "MESSAGE_LOGGER";
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+    public static final String LOG_KEY = "message_data";
+    public static final String LINE_BREAKS = "\n\n";
+
+    public static void logMessage(Context context, String message) {
+        SharedPreferences prefs = getPrefs(context);
+        message = DATE_FORMAT.format(new Date(System.currentTimeMillis())) + ": " + message;
+        prefs.edit()
+                .putString(LOG_KEY, prefs.getString(LOG_KEY, "") + LINE_BREAKS + message)
+                .apply();
+    }
+
+    public static SharedPreferences getPrefs(Context context) {
+        return context.getSharedPreferences(PREF_MESSAGE, Context.MODE_PRIVATE);
+    }
+
+    public static String getAllMessages(Context context) {
+        return getPrefs(context).getString(LOG_KEY, "");
+    }
+
+    public static void clear(Context context) {
+        getPrefs(context).edit().remove(LOG_KEY).apply();
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReadReceiver.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReadReceiver.java
new file mode 100644
index 0000000..1351ffc
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReadReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.app.NotificationManagerCompat;
+import android.util.Log;
+
+public class MessageReadReceiver extends BroadcastReceiver {
+    private static final String TAG = MessageReadReceiver.class.getSimpleName();
+
+    private static final String CONVERSATION_ID = "conversation_id";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "onReceive");
+        int conversationId = intent.getIntExtra(CONVERSATION_ID, -1);
+        if (conversationId != -1) {
+            Log.d(TAG, "Conversation " + conversationId + " was read");
+            MessageLogger.logMessage(context, "Conversation " + conversationId + " was read.");
+            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
+            notificationManager.cancel(conversationId);
+        }
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReplyReceiver.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReplyReceiver.java
new file mode 100644
index 0000000..c9087d2
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessageReplyReceiver.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.RemoteInput;
+import android.util.Log;
+
+/**
+ * A receiver that gets called when a reply is sent to a given conversationId
+ */
+public class MessageReplyReceiver extends BroadcastReceiver {
+
+    private static final String TAG = MessageReplyReceiver.class.getSimpleName();
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (MessagingService.REPLY_ACTION.equals(intent.getAction())) {
+            int conversationId = intent.getIntExtra(MessagingService.CONVERSATION_ID, -1);
+            CharSequence reply = getMessageText(intent);
+            if (conversationId != -1) {
+                Log.d(TAG, "Got reply (" + reply + ") for ConversationId " + conversationId);
+                MessageLogger.logMessage(context, "ConversationId: " + conversationId +
+                        " received a reply: [" + reply + "]");
+            }
+        }
+    }
+
+    /**
+     * Get the message text from the intent.
+     * Note that you should call {@code RemoteInput#getResultsFromIntent(intent)} to process
+     * the RemoteInput.
+     */
+    private CharSequence getMessageText(Intent intent) {
+        Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+        if (remoteInput != null) {
+            return remoteInput.getCharSequence(MessagingService.EXTRA_VOICE_REPLY);
+        }
+        return null;
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingFragment.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingFragment.java
new file mode 100644
index 0000000..2fe75c6
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingFragment.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.text.method.ScrollingMovementMethod;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * The main fragment that shows the buttons and the text view containing the log.
+ */
+public class MessagingFragment extends Fragment implements View.OnClickListener {
+
+    private static final String TAG = MessagingFragment.class.getSimpleName();
+
+    private Button mSendSingleConversation;
+    private Button mSendTwoConversations;
+    private Button mSendConversationWithThreeMessages;
+    private TextView mDataPortView;
+    private Button mClearLogButton;
+
+    private Messenger mService;
+    private boolean mBound;
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName componentName, IBinder service) {
+            mService = new Messenger(service);
+            mBound = true;
+            setButtonsState(true);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName componentName) {
+            mService = null;
+            mBound = false;
+            setButtonsState(false);
+        }
+    };
+
+    private SharedPreferences.OnSharedPreferenceChangeListener listener =
+            new SharedPreferences.OnSharedPreferenceChangeListener() {
+        @Override
+        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+            if (MessageLogger.LOG_KEY.equals(key)) {
+                mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
+            }
+        }
+    };
+
+    public MessagingFragment() {
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View rootView = inflater.inflate(R.layout.fragment_message_me, container, false);
+
+        mSendSingleConversation = (Button) rootView.findViewById(R.id.send_1_conversation);
+        mSendSingleConversation.setOnClickListener(this);
+
+        mSendTwoConversations = (Button) rootView.findViewById(R.id.send_2_conversations);
+        mSendTwoConversations.setOnClickListener(this);
+
+        mSendConversationWithThreeMessages =
+                (Button) rootView.findViewById(R.id.send_1_conversation_3_messages);
+        mSendConversationWithThreeMessages.setOnClickListener(this);
+
+        mDataPortView = (TextView) rootView.findViewById(R.id.data_port);
+        mDataPortView.setMovementMethod(new ScrollingMovementMethod());
+
+        mClearLogButton = (Button) rootView.findViewById(R.id.clear);
+        mClearLogButton.setOnClickListener(this);
+
+        setButtonsState(false);
+
+        return rootView;
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view == mSendSingleConversation) {
+            sendMsg(1, 1);
+        } else if (view == mSendTwoConversations) {
+            sendMsg(2, 1);
+        } else if (view == mSendConversationWithThreeMessages) {
+            sendMsg(1, 3);
+        } else if (view == mClearLogButton) {
+            MessageLogger.clear(getActivity());
+            mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        getActivity().bindService(new Intent(getActivity(), MessagingService.class), mConnection,
+                Context.BIND_AUTO_CREATE);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        MessageLogger.getPrefs(getActivity()).unregisterOnSharedPreferenceChangeListener(listener);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mDataPortView.setText(MessageLogger.getAllMessages(getActivity()));
+        MessageLogger.getPrefs(getActivity()).registerOnSharedPreferenceChangeListener(listener);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (mBound) {
+            getActivity().unbindService(mConnection);
+            mBound = false;
+        }
+    }
+
+    private void sendMsg(int howManyConversations, int messagesPerConversation) {
+        if (mBound) {
+            Message msg = Message.obtain(null, MessagingService.MSG_SEND_NOTIFICATION,
+                    howManyConversations, messagesPerConversation);
+            try {
+                mService.send(msg);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error sending a message", e);
+                MessageLogger.logMessage(getActivity(), "Error occurred while sending a message.");
+            }
+        }
+    }
+
+    private void setButtonsState(boolean enable) {
+        mSendSingleConversation.setEnabled(enable);
+        mSendTwoConversations.setEnabled(enable);
+        mSendConversationWithThreeMessages.setEnabled(enable);
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingService.java b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingService.java
new file mode 100644
index 0000000..d702369
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/java/com/example/android/automessagingdemo/MessagingService.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.automessagingdemo;
+
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.preview.support.v4.app.NotificationCompat.CarExtender;
+import android.preview.support.v4.app.NotificationCompat.CarExtender.UnreadConversation;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.RemoteInput;
+import android.util.Log;
+
+import java.util.Iterator;
+
+public class MessagingService extends Service {
+    private static final String TAG = MessagingService.class.getSimpleName();
+
+    public static final String READ_ACTION =
+            "com.example.messaging.messagemedemo.ACTION_MESSAGE_READ";
+    public static final String REPLY_ACTION =
+            "com.example.messaging.messagemedemo.ACTION_MESSAGE_REPLY";
+    public static final String CONVERSATION_ID = "conversation_id";
+    public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+    public static final int MSG_SEND_NOTIFICATION = 1;
+    public static final String EOL = "\n";
+
+    private NotificationManagerCompat mNotificationManager;
+
+    private final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+    /**
+     * Handler of incoming messages from clients.
+     */
+    class IncomingHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SEND_NOTIFICATION:
+                    int howManyConversations = msg.arg1 <= 0 ? 1 : msg.arg1;
+                    int messagesPerConv = msg.arg2 <= 0 ? 1 : msg.arg2;
+                    sendNotification(howManyConversations, messagesPerConv);
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        Log.d(TAG, "onCreate");
+        mNotificationManager = NotificationManagerCompat.from(getApplicationContext());
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind");
+        return mMessenger.getBinder();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.d(TAG, "onStartCommand");
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.d(TAG, "onDestroy");
+    }
+
+    // Creates an intent that will be triggered when a message is marked as read.
+    private Intent getMessageReadIntent(int id) {
+        return new Intent()
+                .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+                .setAction(READ_ACTION)
+                .putExtra(CONVERSATION_ID, id);
+    }
+
+    // Creates an Intent that will be triggered when a voice reply is received.
+    private Intent getMessageReplyIntent(int conversationId) {
+        return new Intent()
+                .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+                .setAction(REPLY_ACTION)
+                .putExtra(CONVERSATION_ID, conversationId);
+    }
+
+    private void sendNotification(int howManyConversations, int messagesPerConversation) {
+        Conversations.Conversation[] conversations = Conversations.getUnreadConversations(
+                howManyConversations, messagesPerConversation);
+        for (Conversations.Conversation conv : conversations) {
+            sendNotificationForConversation(conv);
+        }
+    }
+
+    private void sendNotificationForConversation(Conversations.Conversation conversation) {
+        // A pending Intent for reads
+        PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
+                conversation.getConversationId(),
+                getMessageReadIntent(conversation.getConversationId()),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        // Build a RemoteInput for receiving voice input in a Car Notification
+        RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+                .setLabel(getApplicationContext().getString(R.string.notification_reply))
+                .build();
+
+        // Building a Pending Intent for the reply action to trigger
+        PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
+                conversation.getConversationId(),
+                getMessageReplyIntent(conversation.getConversationId()),
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        // Create the UnreadConversation and populate it with the participant name,
+        // read and reply intents.
+        UnreadConversation.Builder unreadConvBuilder =
+                new UnreadConversation.Builder(conversation.getParticipantName())
+                .setLatestTimestamp(conversation.getTimestamp())
+                .setReadPendingIntent(readPendingIntent)
+                .setReplyAction(replyIntent, remoteInput);
+
+        // Note: Add messages from oldest to newest to the UnreadConversation.Builder
+        StringBuilder messageForNotification = new StringBuilder();
+        for (Iterator<String> messages = conversation.getMessages().iterator();
+             messages.hasNext(); ) {
+            String message = messages.next();
+            unreadConvBuilder.addMessage(message);
+            messageForNotification.append(message);
+            if (messages.hasNext()) {
+                messageForNotification.append(EOL);
+            }
+        }
+
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
+                .setSmallIcon(R.drawable.notification_icon)
+                .setLargeIcon(BitmapFactory.decodeResource(
+                        getApplicationContext().getResources(), R.drawable.android_contact))
+                .setContentText(messageForNotification.toString())
+                .setWhen(conversation.getTimestamp())
+                .setContentTitle(conversation.getParticipantName())
+                .setContentIntent(readPendingIntent)
+                .extend(new CarExtender()
+                        .setUnreadConversation(unreadConvBuilder.build())
+                        .setColor(getApplicationContext()
+                                .getResources().getColor(R.color.default_color_light)));
+
+        MessageLogger.logMessage(getApplicationContext(), "Sending notification "
+                + conversation.getConversationId() + " conversation: " + conversation);
+
+        mNotificationManager.notify(conversation.getConversationId(), builder.build());
+    }
+}
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-hdpi/ic_launcher.png b/AutoMessagingDemo/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..06d85f1
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-hdpi/notification_icon.png b/AutoMessagingDemo/app/src/main/res/drawable-hdpi/notification_icon.png
new file mode 100644
index 0000000..9cdfca1
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-hdpi/notification_icon.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-mdpi/ic_launcher.png b/AutoMessagingDemo/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4e1cc86
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-mdpi/notification_icon.png b/AutoMessagingDemo/app/src/main/res/drawable-mdpi/notification_icon.png
new file mode 100644
index 0000000..d6069eb
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-mdpi/notification_icon.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png b/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..92f1e2d
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/notification_icon.png b/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/notification_icon.png
new file mode 100644
index 0000000..786ed17
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-xhdpi/notification_icon.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/android_contact.png b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/android_contact.png
new file mode 100644
index 0000000..611d565
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/android_contact.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2476cbd
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/notification_icon.png b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/notification_icon.png
new file mode 100644
index 0000000..005207c
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/drawable-xxhdpi/notification_icon.png
Binary files differ
diff --git a/AutoMessagingDemo/app/src/main/res/layout-land/fragment_message_me.xml b/AutoMessagingDemo/app/src/main/res/layout-land/fragment_message_me.xml
new file mode 100644
index 0000000..8f7b60a
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/layout-land/fragment_message_me.xml
@@ -0,0 +1,67 @@
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:gravity="center_horizontal"
+              android:orientation="horizontal"
+              android:paddingBottom="@dimen/activity_vertical_margin"
+              android:paddingLeft="@dimen/activity_horizontal_margin"
+              android:paddingRight="@dimen/activity_horizontal_margin"
+              android:paddingTop="@dimen/activity_vertical_margin">
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <Button
+            android:id="@+id/send_1_conversation"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/send_1_conversation"/>
+
+        <Button
+            android:id="@+id/send_2_conversations"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/send_2_conversations"/>
+
+        <Button
+            android:id="@+id/send_1_conversation_3_messages"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/send_1_conv_3_messages"/>
+    </LinearLayout>
+    <RelativeLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="2">
+        <Button
+            android:id="@+id/clear"
+            android:layout_alignParentBottom="true"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/clear_log"/>
+
+        <TextView
+            android:id="@+id/data_port"
+            android:layout_above="@id/clear"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:maxLines="20"
+            android:scrollbars="vertical"/>
+    </RelativeLayout>
+</LinearLayout>
diff --git a/AutoMessagingDemo/app/src/main/res/layout/activity_main.xml b/AutoMessagingDemo/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..79f6adf
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,22 @@
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MessageMeActivity"
+    tools:ignore="MergeRootFrame" />
diff --git a/AutoMessagingDemo/app/src/main/res/layout/fragment_message_me.xml b/AutoMessagingDemo/app/src/main/res/layout/fragment_message_me.xml
new file mode 100644
index 0000000..e673f0d
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/layout/fragment_message_me.xml
@@ -0,0 +1,58 @@
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical"
+              android:gravity="center_horizontal"
+              android:paddingBottom="@dimen/activity_vertical_margin"
+              android:paddingLeft="@dimen/activity_horizontal_margin"
+              android:paddingRight="@dimen/activity_horizontal_margin"
+              android:paddingTop="@dimen/activity_vertical_margin">
+
+    <Button
+        android:id="@+id/send_1_conversation"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/send_1_conversation"/>
+
+    <Button
+        android:id="@+id/send_2_conversations"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/send_2_conversations"/>
+
+    <Button
+        android:id="@+id/send_1_conversation_3_messages"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/send_1_conv_3_messages"/>
+
+    <TextView
+        android:id="@+id/data_port"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:maxLines="20"
+        android:scrollbars="vertical"/>
+    <Button
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/clear"
+        android:text="@string/clear_log"/>
+
+</LinearLayout>
diff --git a/AutoMessagingDemo/app/src/main/res/values-v21/styles.xml b/AutoMessagingDemo/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..f30c97a
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <style name="AppTheme" parent="android:Theme.Material.Light">
+        <item name="android:colorPrimary">@color/default_color_light</item>
+        <item name="android:colorPrimaryDark">@color/default_color_dark</item>
+    </style>
+</resources>
diff --git a/AutoMessagingDemo/app/src/main/res/values/colors.xml b/AutoMessagingDemo/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..0e6825b
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <color name="default_color_light">#ff4092c3</color>
+    <color name="default_color_dark">#ff241c99</color>
+</resources>
diff --git a/AutoMessagingDemo/app/src/main/res/values/dimens.xml b/AutoMessagingDemo/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..574a35d
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/AutoMessagingDemo/app/src/main/res/values/strings.xml b/AutoMessagingDemo/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..001b10e
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/values/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <string name="app_name">Messaging Sample</string>
+    <string name="action_settings">Settings</string>
+    <string name="title">Messaging Sample</string>
+    <string name="notification_reply">Reply by Voice</string>
+    <string name="send_2_conversations">Send 2 conversations with 1 message</string>
+    <string name="send_1_conversation">Send 1 conversation with 1 message</string>
+    <string name="send_1_conv_3_messages">Send 1 conversation with 3 messages</string>
+    <string name="clear_log">Clear Log</string>
+</resources>
diff --git a/AutoMessagingDemo/app/src/main/res/values/styles.xml b/AutoMessagingDemo/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..3f1a6af
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<resources>
+    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+    </style>
+</resources>
diff --git a/AutoMessagingDemo/app/src/main/res/xml/automotive_app_desc.xml b/AutoMessagingDemo/app/src/main/res/xml/automotive_app_desc.xml
new file mode 100644
index 0000000..9e9f174
--- /dev/null
+++ b/AutoMessagingDemo/app/src/main/res/xml/automotive_app_desc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<automotiveApp>
+    <uses name="notification"/>
+</automotiveApp>
diff --git a/AutoMessagingDemo/build.gradle b/AutoMessagingDemo/build.gradle
new file mode 100644
index 0000000..9b8abe4
--- /dev/null
+++ b/AutoMessagingDemo/build.gradle
@@ -0,0 +1,19 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:0.12.2'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+    }
+}
diff --git a/AutoMessagingDemo/gradle.properties b/AutoMessagingDemo/gradle.properties
new file mode 100644
index 0000000..34fb461
--- /dev/null
+++ b/AutoMessagingDemo/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Settings specified in this file will override any Gradle settings
+# configured through the IDE.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.jar b/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.properties b/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..1e61d1f
--- /dev/null
+++ b/AutoMessagingDemo/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
diff --git a/AutoMessagingDemo/gradlew b/AutoMessagingDemo/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/AutoMessagingDemo/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/AutoMessagingDemo/settings.gradle b/AutoMessagingDemo/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/AutoMessagingDemo/settings.gradle
@@ -0,0 +1 @@
+include ':app'