Merge "Separate MediaRecorderClient with MediaPlayerClient" into gingerbread
diff --git a/core/res/res/drawable-hdpi/presence_audio_away.png b/core/res/res/drawable-hdpi/presence_audio_away.png
index f18b6c9..fb5e123 100644
--- a/core/res/res/drawable-hdpi/presence_audio_away.png
+++ b/core/res/res/drawable-hdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_busy.png b/core/res/res/drawable-hdpi/presence_audio_busy.png
index ae7b983..81aeb01 100644
--- a/core/res/res/drawable-hdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-hdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_online.png b/core/res/res/drawable-hdpi/presence_audio_online.png
index 15e4513..553acbb 100644
--- a/core/res/res/drawable-hdpi/presence_audio_online.png
+++ b/core/res/res/drawable-hdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index d4aa66b..84b00bb 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_busy.png b/core/res/res/drawable-hdpi/presence_busy.png
index 4b27853..d77a463 100644
--- a/core/res/res/drawable-hdpi/presence_busy.png
+++ b/core/res/res/drawable-hdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_invisible.png b/core/res/res/drawable-hdpi/presence_invisible.png
index 0e27fba..0d83e70a 100644
--- a/core/res/res/drawable-hdpi/presence_invisible.png
+++ b/core/res/res/drawable-hdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_offline.png b/core/res/res/drawable-hdpi/presence_offline.png
index e511aa4..2619e9f 100644
--- a/core/res/res/drawable-hdpi/presence_offline.png
+++ b/core/res/res/drawable-hdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_online.png b/core/res/res/drawable-hdpi/presence_online.png
index d787d2f..7e846ef 100644
--- a/core/res/res/drawable-hdpi/presence_online.png
+++ b/core/res/res/drawable-hdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_away.png b/core/res/res/drawable-hdpi/presence_video_away.png
index f18b6c9..ab5493b 100644
--- a/core/res/res/drawable-hdpi/presence_video_away.png
+++ b/core/res/res/drawable-hdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_busy.png b/core/res/res/drawable-hdpi/presence_video_busy.png
index ae7b983..456cdb0 100644
--- a/core/res/res/drawable-hdpi/presence_video_busy.png
+++ b/core/res/res/drawable-hdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_online.png b/core/res/res/drawable-hdpi/presence_video_online.png
index 15e4513..bd9f8a4 100644
--- a/core/res/res/drawable-hdpi/presence_video_online.png
+++ b/core/res/res/drawable-hdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_away.png b/core/res/res/drawable-mdpi/presence_audio_away.png
index f67e64e..db96754 100644
--- a/core/res/res/drawable-mdpi/presence_audio_away.png
+++ b/core/res/res/drawable-mdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_busy.png b/core/res/res/drawable-mdpi/presence_audio_busy.png
index 0ad991b..0a29948 100644
--- a/core/res/res/drawable-mdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-mdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_online.png b/core/res/res/drawable-mdpi/presence_audio_online.png
index 6cc3d1a..df415ba 100644
--- a/core/res/res/drawable-mdpi/presence_audio_online.png
+++ b/core/res/res/drawable-mdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_away.png b/core/res/res/drawable-mdpi/presence_away.png
index f8120df..f98e908 100644
--- a/core/res/res/drawable-mdpi/presence_away.png
+++ b/core/res/res/drawable-mdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_busy.png b/core/res/res/drawable-mdpi/presence_busy.png
index 9d7620b..933261f4 100644
--- a/core/res/res/drawable-mdpi/presence_busy.png
+++ b/core/res/res/drawable-mdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_invisible.png b/core/res/res/drawable-mdpi/presence_invisible.png
index 21399a4..8d72756 100644
--- a/core/res/res/drawable-mdpi/presence_invisible.png
+++ b/core/res/res/drawable-mdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_offline.png b/core/res/res/drawable-mdpi/presence_offline.png
index 3941b82..fc78396 100644
--- a/core/res/res/drawable-mdpi/presence_offline.png
+++ b/core/res/res/drawable-mdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_online.png b/core/res/res/drawable-mdpi/presence_online.png
index 22d5683..943eee0 100644
--- a/core/res/res/drawable-mdpi/presence_online.png
+++ b/core/res/res/drawable-mdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_away.png b/core/res/res/drawable-mdpi/presence_video_away.png
index f67e64e..f3ec5d4 100644
--- a/core/res/res/drawable-mdpi/presence_video_away.png
+++ b/core/res/res/drawable-mdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_busy.png b/core/res/res/drawable-mdpi/presence_video_busy.png
index 0ad991b..7379e00 100644
--- a/core/res/res/drawable-mdpi/presence_video_busy.png
+++ b/core/res/res/drawable-mdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_online.png b/core/res/res/drawable-mdpi/presence_video_online.png
index 6cc3d1a..24ceb39 100644
--- a/core/res/res/drawable-mdpi/presence_video_online.png
+++ b/core/res/res/drawable-mdpi/presence_video_online.png
Binary files differ
diff --git a/docs/html/guide/developing/tools/bmgr.jd b/docs/html/guide/developing/tools/bmgr.jd
index 2f49532..57deb25 100644
--- a/docs/html/guide/developing/tools/bmgr.jd
+++ b/docs/html/guide/developing/tools/bmgr.jd
@@ -15,6 +15,11 @@
 <li><a href="#other">Other Commands</a></li>
   </ol>
 
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a></li>
+  </ol>
+
 </div>
 </div>
 
@@ -26,6 +31,9 @@
 intrusive steps in order to test your application's backup agent.  These commands are
 accessed via the <a href="{@docRoot}guide/developing/tools/adb.html">adb</a> shell.
 
+<p>For information about adding support for backup in your application, read <a
+href="{@docRoot}guide/topics/data/backup.html">Data Backup</a>, which includes a guide to testing
+your application using {@code bmgr}.</p>
 
 
 <h2 id="backup">Forcing a Backup Operation</h2>
@@ -90,6 +98,8 @@
 
 <h2 id="other">Other Commands</h2>
 
+<h3>Wiping data</h3>
+
 <p>The data for a single application can be erased from the active data set on demand.  This is
 very useful while you're developing a backup agent, in case bugs lead you to write corrupt data
 or saved state information. You can wipe an application's data with the <code>bmgr wipe</code>
@@ -102,6 +112,9 @@
 erase.  The next backup operation that the application's agent processes will look as
 though the application had never backed anything up before.
 
+
+<h3>Enabling and disabling backup</h3>
+
 <p>You can see whether the Backup Manager is operational at all with the <code>bmgr
 enabled</code> command:
 
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd
index 4e74a83..4279d7d 100644
--- a/docs/html/guide/topics/data/backup.jd
+++ b/docs/html/guide/topics/data/backup.jd
@@ -33,7 +33,7 @@
     <li><a href="#RestoreVersion">Checking the Restore Data Version</a></li>
     <li><a href="#RequestingBackup">Requesting Backup</a></li>
     <li><a href="#RequestingRestore">Requesting Restore</a></li>
-    <li><a href="#DevelopingTesting">Developing and Testing Your Backup Agent</a></li>
+    <li><a href="#Testing">Testing Your Backup Agent</a></li>
   </ol>
 
   <h2>Key classes</h2>
@@ -43,6 +43,11 @@
     <li>{@link android.app.backup.BackupAgentHelper}</li>
   </ol>
 
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr} tool</a></li>
+  </ol>
+
 </div>
 </div>
 
@@ -308,7 +313,7 @@
 
 <p class="note"><strong>Tip:</strong> While developing your application, you can initiate an
 immediate backup operation from the Backup Manager with the <a
-href="{@docRoot}guide/developing/tools/bmgr.html">bmgr tool</a>.</p>
+href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr} tool</a>.</p>
 
 <p>When the Backup Manager calls your {@link
 android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
@@ -452,7 +457,7 @@
 href="#RequestingRestore">Requesting restore</a> for more information).</p>
 
 <p class="note"><strong>Note:</strong> While developing your application, you can also request a
-restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
+restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
 tool</a>.</p>
 
 <p>When the Backup Manager calls your {@link
@@ -813,7 +818,7 @@
 
 <p class="note"><strong>Note:</strong> While developing your application, you can request a
 backup and initiate an immediate backup operation with the <a
-href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
+href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
 tool</a>.</p>
 
 
@@ -828,25 +833,52 @@
 implementation, passing the data from the current set of backup data.</p>
 
 <p class="note"><strong>Note:</strong> While developing your application, you can request a
-restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">bmgr
+restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
 tool</a>.</p>
 
 
-<h2 id="DevelopingTesting">Developing and Testing Your Backup Agent</h2>
+<h2 id="Testing">Testing Your Backup Agent</h2>
 
-<p>To develop and test your backup agent:</p>
-<ul>
-  <li>Set your build target to a platform using API Level 8 or higher</li>
-  <li>Run your application on a suitable Android system image:
+<p>Once you've implemented your backup agent, you can test the backup and restore functionality
+with the following procedure, using <a
+href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}</a>.</p>
+
+<ol>
+  <li>Install your application on a suitable Android system image
     <ul>
-      <li>If using the emulator, create and use an AVD with the Google APIs add-on (API Level
-8) &mdash; the Google APIs add-on is available as an SDK component through the SDK and AVD
-Manager</li>
+      <li>If using the emulator, create and use an AVD with Android 2.2 (API Level 8).</li>
       <li>If using a device, the device must be running Android 2.2 or greater and have Android
-Market built in</li>
+Market built in.</li>
     </ul>
   </li>
-  <li>Test your backup agent using the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code
-bmgr}</a> tool to initiate backup and restore operations</li>
-</ul>
+  <li>Ensure that backup is enabled
+    <ul>
+      <li>If using the emulator, you can enable backup with the following command from your SDK
+{@code tools/} path:
+<pre class="no-pretty-print">adb shell bmgr enable true</pre>
+      </li>
+      <li>If using a device, open the system <b>Settings</b>, select <b>Privacy</b>, then enable
+<b>Back up my data</b> and <b>Automatic restore</b>.
+    </ul>
+  </li>
+  <li>Open your application and initialize some data
+    <p>If you've properly implemented backup in your application, then it should request a
+backup each time the data changes. For example, each time the user changes some data, your app
+should call {@link android.app.backup.BackupManager#dataChanged()}, which adds a backup request to
+the Backup Manager queue. For testing purposes, you can also make a request with the following
+{@code bmgr} command:</p>
+<pre class="no-pretty-print">adb shell bmgr backup <em>your.package.name</em></pre>
+  </li>
+  <li>Initiate a backup operation:
+<pre class="no-pretty-print">adb shell bmgr run</pre>
+    <p>This forces the Backup Manager to perform all backup requests that are in its
+queue.</p>
+  <li>Uninstall your application:
+<pre class="no-pretty-print">adb uninstall <em>your.package.name</em></pre>
+  </li>
+  <li>Re-install your application.</li>
+</ol>
+
+<p>If your backup agent is successful, all the data you initialized in step 4 is restored.</p>
+
 
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background.9.png
new file mode 100644
index 0000000..7000eee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background.9.png
new file mode 100644
index 0000000..258de13
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/intruder_alert.xml b/packages/SystemUI/res/layout/intruder_alert.xml
new file mode 100644
index 0000000..58dc333
--- /dev/null
+++ b/packages/SystemUI/res/layout/intruder_alert.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!--    android:background="@drawable/status_bar_closed_default_background" -->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:background="@drawable/alert_bar_background"
+    android:orientation="horizontal"
+    android:focusable="true"
+    android:descendantFocusability="afterDescendants"
+    >
+        
+    <LinearLayout 
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingLeft="6dip"
+        android:animationCache="false"
+        android:orientation="horizontal"
+        >
+
+        <ImageView
+            android:id="@+id/alertIcon"
+            android:layout_width="25dip"
+            android:layout_height="25dip"
+            android:layout_marginRight="8dip"
+            />
+        <TextView
+            android:id="@+id/alertText"
+            android:textAppearance="@*android:style/TextAppearance.StatusBar.EventContent"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            />
+    </LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index 5d16e93..3c14fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -57,6 +57,7 @@
 import android.view.WindowManagerImpl;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 import android.widget.ScrollView;
@@ -84,6 +85,11 @@
 
     private static final int MSG_ANIMATE = 1000;
     private static final int MSG_ANIMATE_REVEAL = 1001;
+    private static final int MSG_SHOW_INTRUDER = 1002;
+    private static final int MSG_HIDE_INTRUDER = 1003;
+
+    // will likely move to a resource or other tunable param at some point
+    private static final int INTRUDER_ALERT_DECAY_MS = 10000;
 
     private class ExpandedDialog extends Dialog {
         ExpandedDialog(Context context) {
@@ -180,6 +186,9 @@
     // for disabling the status bar
     int mDisabled = 0;
 
+    // for immersive activities
+    private View mIntruderAlertView;
+
     /**
      * Construct the service, add the status bar view to the window manager
      */
@@ -208,6 +217,17 @@
         ExpandedView expanded = (ExpandedView)View.inflate(context,
                 R.layout.status_bar_expanded, null);
         expanded.mService = this;
+
+        mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null);
+        mIntruderAlertView.setVisibility(View.GONE);
+        mIntruderAlertView.setClickable(true);
+        mIntruderAlertView.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                Slog.d(TAG, "Intruder Alert clicked!");
+                mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
+            }
+        });
+
         StatusBarView sb = (StatusBarView)View.inflate(context, R.layout.status_bar, null);
         sb.mService = this;
 
@@ -286,6 +306,23 @@
         // TODO lp.windowAnimations = R.style.Animation_StatusBar;
 
         WindowManagerImpl.getDefault().addView(view, lp);
+
+        lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                mHeight,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                PixelFormat.TRANSLUCENT);
+        lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+        lp.y += mHeight * 1.5; // for now
+        lp.setTitle("IntruderAlert");
+        lp.windowAnimations = android.R.style.Animation_Dialog;
+
+        WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
     }
 
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
@@ -310,7 +347,8 @@
     }
 
     public void addNotification(IBinder key, StatusBarNotification notification) {
-        addNotificationViews(key, notification);
+        StatusBarIconView iconView = addNotificationViews(key, notification);
+        if (iconView == null) return;
 
         boolean immersive = false;
         try {
@@ -322,21 +360,22 @@
             if ((notification.notification.flags & Notification.FLAG_HIGH_PRIORITY) != 0) {
                 Slog.d(TAG, "Presenting high-priority notification in immersive activity");
                 // @@@ special new transient ticker mode
-                /*
-                // 1. Populate mAlertBarView
+                // 1. Populate mIntruderAlertView
 
-                ImageView alertIcon = (ImageView) mAlertBarView.findViewById(R.id.alertIcon);
-                TextView alertText = (TextView) mAlertBarView.findViewById(R.id.alertText);
+                ImageView alertIcon = (ImageView) mIntruderAlertView.findViewById(R.id.alertIcon);
+                TextView alertText = (TextView) mIntruderAlertView.findViewById(R.id.alertText);
                 alertIcon.setImageDrawable(StatusBarIconView.getIcon(
                     alertIcon.getContext(), 
                     iconView.getStatusBarIcon()));
                 alertText.setText(notification.notification.tickerText);
 
-                // 2. Animate mAlertBarView in
-                mAlertBarView.setVisibility(View.VISIBLE);
+                // 2. Animate mIntruderAlertView in
+                mHandler.removeMessages(MSG_HIDE_INTRUDER);
+                mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
+                mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
 
                 // 3. Set alarm to age the notification off (TODO)
-                */
+                
             }
         } else if (notification.notification.fullScreenIntent != null) {
             // not immersive & a full-screen alert should be shown
@@ -502,7 +541,7 @@
         return new View[] { row, content, expanded };
     }
 
-    void addNotificationViews(IBinder key, StatusBarNotification notification) {
+    StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
         NotificationData list;
         ViewGroup parent;
         final boolean isOngoing = notification.isOngoing();
@@ -518,7 +557,7 @@
         if (views == null) {
             handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
                     + notification);
-            return;
+            return null;
         }
         final View row = views[0];
         final View content = views[1];
@@ -530,7 +569,7 @@
                     notification.notification.iconLevel, notification.notification.number);
         if (!iconView.set(ic)) {
             handleNotificationError(key, notification, "Coulding create icon: " + ic);
-            return;
+            return null;
         }
         // Add the expanded view.
         final int viewIndex = list.add(key, notification, row, content, expanded, iconView);
@@ -539,6 +578,8 @@
         final int iconIndex = chooseIconIndex(isOngoing, viewIndex);
         mNotificationIcons.addView(iconView, iconIndex,
                 new LinearLayout.LayoutParams(mIconWidth, mHeight));
+
+        return iconView;
     }
 
     StatusBarNotification removeNotificationViews(IBinder key) {
@@ -628,6 +669,12 @@
                 case MSG_ANIMATE_REVEAL:
                     doRevealAnimation();
                     break;
+                case MSG_SHOW_INTRUDER:
+                    setIntruderAlertVisibility(true);
+                    break;
+                case MSG_HIDE_INTRUDER:
+                    setIntruderAlertVisibility(false);
+                    break;
             }
         }
     }
@@ -1440,6 +1487,10 @@
         }
     };
 
+    private void setIntruderAlertVisibility(boolean vis) {
+        mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
+    }
+
     /**
      * Reload some of our resources when the configuration changes.
      *