Merge "Delay AccountManagerService initialization" into jb-dev
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 96a6438..a509156 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -1056,7 +1056,12 @@
         rc = -errno;
         goto out;
     }
-
+    if (chmod(libdir, 0755) < 0) {
+        ALOGE("cannot chmod dir '%s': %s\n", libdir, strerror(errno));
+        unlink(libdir);
+        rc = -errno;
+        goto out;
+    }
     if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
         ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
         unlink(libdir);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b902550..411f6d0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -361,10 +361,10 @@
                     return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
                 }});
 
-        registerService(LOCATION_SERVICE, new StaticServiceFetcher() {
-                public Object createStaticService() {
+        registerService(LOCATION_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(LOCATION_SERVICE);
-                    return new LocationManager(ILocationManager.Stub.asInterface(b));
+                    return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
                 }});
 
         registerService(NETWORK_POLICY_SERVICE, new ServiceFetcher() {
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index 06b63a0c..99ab9cb 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -1,4 +1,6 @@
-page.title=Android 4.1 API Overview
+page.title=Android 4.0 Platform
+sdk.platform.version=4.0
+sdk.platform.apiLevel=14
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/design/building-blocks/dialogs.jd b/docs/html/design/building-blocks/dialogs.jd
index 9b653ee..2820471 100644
--- a/docs/html/design/building-blocks/dialogs.jd
+++ b/docs/html/design/building-blocks/dialogs.jd
@@ -10,28 +10,29 @@
 <div class="with-callouts">
 
 <ol>
-<li>
-<h4>Optional title region</h4>
-<p>The title introduces the content of your dialog. It can, for example, identify the name of a
- setting that the user is about to change, or request a decision.</p>
-</li>
-<li>
-<h4>Content area</h4>
-<p>Dialog content varies widely. For settings dialogs, a dialog may contain UI elements such as
- sliders, text fields, checkboxes, or radio buttons that allow the user to change app or system
- settings. In other cases, such as alerts, the content may consist solely of text that provides
- further context for a user decision.</p>
-</li>
-<li>
-<h4>Action buttons</h4>
-<p>Action buttons are typically Cancel and/or OK, with OK indicating the preferred or most likely
- action. However, if the options consist of specific actions such as Close or Wait rather than
- a confirmation or cancellation of the action described in the content, then all the buttons
- should be active verbs. As a rule, the dismissive action of a dialog is always on the left
- whereas the affirmative actions are on the right.</p>
-</li>
-</ol>
+  <li>
+  <h4>Optional title region</h4>
+  <p>The title introduces the content of your dialog. It can, for example, identify the name of a
+   setting that the user is about to change, or request a decision.</p>
+  </li>
+  <li>
+  <h4>Content area</h4>
+  <p>Dialog content varies widely. For settings dialogs, a dialog may contain UI elements such as
+   sliders, text fields, checkboxes, or radio buttons that allow the user to change app or system
+   settings. In other cases, such as alerts, the content may consist solely of text that provides
+   further context for a user decision.</p>
+  </li>
 
+  <li>
+  <h4>Action buttons</h4>
+  <p>Action buttons are typically Cancel and/or OK, with OK indicating the preferred or most likely action. However, if the options consist of specific actions such as Close or Wait rather than a confirmation or cancellation of the action described in the content, then all the buttons should be active verbs. Order actions following these rules:</p>
+    <ul>
+    
+    <li>The dismissive action of a dialog is always on the left. Dismissive actions return to the user to the previous state.</li>
+    <li>The affirmative actions are on the right. Affirmative actions continue progress toward the user goal that triggered the dialog.</li>
+    </ul>
+  </li>
+</ol>
 </div>
 
 <img src="{@docRoot}design/media/dialogs_examples.png">
diff --git a/docs/html/design/building-blocks/index.jd b/docs/html/design/building-blocks/index.jd
index d915aae..e554775 100644
--- a/docs/html/design/building-blocks/index.jd
+++ b/docs/html/design/building-blocks/index.jd
@@ -11,7 +11,7 @@
 #text-overlay {
   position: absolute;
   left: 0;
-  top: 472px;
+  top: 520px;
   width: 450px;
 }
 </style>
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
index 19ed1c3..8a2eb41 100644
--- a/docs/html/design/building-blocks/tabs.jd
+++ b/docs/html/design/building-blocks/tabs.jd
@@ -6,6 +6,7 @@
 <p>Tabs in the action bar make it easy to explore and switch between different views or functional
 aspects of your app, or to browse categorized data sets.</p>
 
+<p>For details on using gestures to move between tabs, see the <a href="{@docRoot}design/patterns/swipe-views.html">Swipe Views</a> pattern.</p>
 
 <h2 id="scrollable">Scrollable Tabs</h2>
 
@@ -36,7 +37,7 @@
 <h2 id="fixed">Fixed Tabs</h2>
 
 
-<p>Fixed tabs display all items concurrently. To navigate to a different view, touch the tab.</p>
+<p>Fixed tabs display all items concurrently. To navigate to a different view, touch the tab, or swipe left or right.</p>
 
 <img src="{@docRoot}design/media/tabs_standard.png">
 <div class="figure-caption">
diff --git a/docs/html/design/design_toc.cs b/docs/html/design/design_toc.cs
index a31fdd3..17e08f2 100644
--- a/docs/html/design/design_toc.cs
+++ b/docs/html/design/design_toc.cs
@@ -36,7 +36,9 @@
       <li><a href="<?cs var:toroot ?>design/patterns/selection.html">Selection</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/notifications.html">Notifications</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/settings.html">Settings</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/help.html">Help</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/compatibility.html">Compatibility</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/accessibility.html">Accessibility</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/pure-android.html">Pure Android</a></li>
     </ul>
   </li>
diff --git a/docs/html/design/media/accessibility_contentdesc.png b/docs/html/design/media/accessibility_contentdesc.png
new file mode 100644
index 0000000..b4a5c2d
--- /dev/null
+++ b/docs/html/design/media/accessibility_contentdesc.png
Binary files differ
diff --git a/docs/html/design/media/actionbar_drawer.png b/docs/html/design/media/actionbar_drawer.png
new file mode 100644
index 0000000..95e04f5
--- /dev/null
+++ b/docs/html/design/media/actionbar_drawer.png
Binary files differ
diff --git a/docs/html/design/media/app_structure_book_detail_page_flip.png b/docs/html/design/media/app_structure_book_detail_page_flip.png
index 0cca587..1066094 100644
--- a/docs/html/design/media/app_structure_book_detail_page_flip.png
+++ b/docs/html/design/media/app_structure_book_detail_page_flip.png
Binary files differ
diff --git a/docs/html/design/media/app_structure_gallery_filmstrip.png b/docs/html/design/media/app_structure_gallery_filmstrip.png
index 483bafa..a937533 100644
--- a/docs/html/design/media/app_structure_gallery_filmstrip.png
+++ b/docs/html/design/media/app_structure_gallery_filmstrip.png
Binary files differ
diff --git a/docs/html/design/media/building_blocks_landing.png b/docs/html/design/media/building_blocks_landing.png
index 2da47b7..40ab0da 100644
--- a/docs/html/design/media/building_blocks_landing.png
+++ b/docs/html/design/media/building_blocks_landing.png
Binary files differ
diff --git a/docs/html/design/media/color_spectrum.png b/docs/html/design/media/color_spectrum.png
index 7d2c023..b7ab309 100644
--- a/docs/html/design/media/color_spectrum.png
+++ b/docs/html/design/media/color_spectrum.png
Binary files differ
diff --git a/docs/html/design/media/compatibility_physical_buttons.png b/docs/html/design/media/compatibility_physical_buttons.png
index 30d5ddd..66a23c8 100644
--- a/docs/html/design/media/compatibility_physical_buttons.png
+++ b/docs/html/design/media/compatibility_physical_buttons.png
Binary files differ
diff --git a/docs/html/design/media/compatibility_virtual_nav.png b/docs/html/design/media/compatibility_virtual_nav.png
index ea595a4..27d39b2 100644
--- a/docs/html/design/media/compatibility_virtual_nav.png
+++ b/docs/html/design/media/compatibility_virtual_nav.png
Binary files differ
diff --git a/docs/html/design/media/dialogs_popups_example.png b/docs/html/design/media/dialogs_popups_example.png
index 2deb00d..c7536f3 100644
--- a/docs/html/design/media/dialogs_popups_example.png
+++ b/docs/html/design/media/dialogs_popups_example.png
Binary files differ
diff --git a/docs/html/design/media/help_better.png b/docs/html/design/media/help_better.png
new file mode 100644
index 0000000..fde5cb2
--- /dev/null
+++ b/docs/html/design/media/help_better.png
Binary files differ
diff --git a/docs/html/design/media/help_cling.png b/docs/html/design/media/help_cling.png
new file mode 100644
index 0000000..c91d189
--- /dev/null
+++ b/docs/html/design/media/help_cling.png
Binary files differ
diff --git a/docs/html/design/media/help_dont.png b/docs/html/design/media/help_dont.png
new file mode 100644
index 0000000..a1c9841
--- /dev/null
+++ b/docs/html/design/media/help_dont.png
Binary files differ
diff --git a/docs/html/design/media/help_evenbetter.png b/docs/html/design/media/help_evenbetter.png
new file mode 100644
index 0000000..beb88f8
--- /dev/null
+++ b/docs/html/design/media/help_evenbetter.png
Binary files differ
diff --git a/docs/html/design/media/help_overflow.png b/docs/html/design/media/help_overflow.png
new file mode 100644
index 0000000..fb2bc0a
--- /dev/null
+++ b/docs/html/design/media/help_overflow.png
Binary files differ
diff --git a/docs/html/design/media/help_solo_overflow.png b/docs/html/design/media/help_solo_overflow.png
new file mode 100644
index 0000000..9423ede
--- /dev/null
+++ b/docs/html/design/media/help_solo_overflow.png
Binary files differ
diff --git a/docs/html/design/media/index_landing_page.png b/docs/html/design/media/index_landing_page.png
index 3f319b0..2065344 100644
--- a/docs/html/design/media/index_landing_page.png
+++ b/docs/html/design/media/index_landing_page.png
Binary files differ
diff --git a/docs/html/design/media/multipane_show.png b/docs/html/design/media/multipane_show.png
index b10c91c..9993c9b 100644
--- a/docs/html/design/media/multipane_show.png
+++ b/docs/html/design/media/multipane_show.png
Binary files differ
diff --git a/docs/html/design/media/notifications_dismiss.png b/docs/html/design/media/notifications_dismiss.png
index 71bed4f..696a97f 100644
--- a/docs/html/design/media/notifications_dismiss.png
+++ b/docs/html/design/media/notifications_dismiss.png
Binary files differ
diff --git a/docs/html/design/media/notifications_expand_contract_msg.png b/docs/html/design/media/notifications_expand_contract_msg.png
new file mode 100644
index 0000000..f37ec2c
--- /dev/null
+++ b/docs/html/design/media/notifications_expand_contract_msg.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_additional_fail.png b/docs/html/design/media/notifications_pattern_additional_fail.png
index 707c98c..4f056db 100644
--- a/docs/html/design/media/notifications_pattern_additional_fail.png
+++ b/docs/html/design/media/notifications_pattern_additional_fail.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_additional_win.png b/docs/html/design/media/notifications_pattern_additional_win.png
index eb193d8..9d69dfd 100644
--- a/docs/html/design/media/notifications_pattern_additional_win.png
+++ b/docs/html/design/media/notifications_pattern_additional_win.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_anatomy.png b/docs/html/design/media/notifications_pattern_anatomy.png
index cacc183..c9fdf85 100644
--- a/docs/html/design/media/notifications_pattern_anatomy.png
+++ b/docs/html/design/media/notifications_pattern_anatomy.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_expand_contract.png b/docs/html/design/media/notifications_pattern_expand_contract.png
new file mode 100644
index 0000000..e89835c
--- /dev/null
+++ b/docs/html/design/media/notifications_pattern_expand_contract.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_expandable.png b/docs/html/design/media/notifications_pattern_expandable.png
new file mode 100644
index 0000000..30926760
--- /dev/null
+++ b/docs/html/design/media/notifications_pattern_expandable.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_ongoing_music.png b/docs/html/design/media/notifications_pattern_ongoing_music.png
index 01039bd..77b24ed 100644
--- a/docs/html/design/media/notifications_pattern_ongoing_music.png
+++ b/docs/html/design/media/notifications_pattern_ongoing_music.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_personal.png b/docs/html/design/media/notifications_pattern_personal.png
new file mode 100644
index 0000000..08880b2
--- /dev/null
+++ b/docs/html/design/media/notifications_pattern_personal.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_phone_icons.png b/docs/html/design/media/notifications_pattern_phone_icons.png
index 09d8a83..bee66c9 100644
--- a/docs/html/design/media/notifications_pattern_phone_icons.png
+++ b/docs/html/design/media/notifications_pattern_phone_icons.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_priority.png b/docs/html/design/media/notifications_pattern_priority.png
new file mode 100644
index 0000000..e89835c
--- /dev/null
+++ b/docs/html/design/media/notifications_pattern_priority.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_real_time_people.png b/docs/html/design/media/notifications_pattern_real_time_people.png
index 2af40b8..d03b6f0 100644
--- a/docs/html/design/media/notifications_pattern_real_time_people.png
+++ b/docs/html/design/media/notifications_pattern_real_time_people.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_social_fail.png b/docs/html/design/media/notifications_pattern_social_fail.png
index 2c8fddc..aa0e028 100644
--- a/docs/html/design/media/notifications_pattern_social_fail.png
+++ b/docs/html/design/media/notifications_pattern_social_fail.png
Binary files differ
diff --git a/docs/html/design/media/notifications_pattern_two_actions.png b/docs/html/design/media/notifications_pattern_two_actions.png
new file mode 100644
index 0000000..7c19f2e
--- /dev/null
+++ b/docs/html/design/media/notifications_pattern_two_actions.png
Binary files differ
diff --git a/docs/html/design/media/principles_decide_for_me.png b/docs/html/design/media/principles_decide_for_me.png
index 2d8b883..8080b4e 100644
--- a/docs/html/design/media/principles_decide_for_me.png
+++ b/docs/html/design/media/principles_decide_for_me.png
Binary files differ
diff --git a/docs/html/design/media/principles_error.png b/docs/html/design/media/principles_error.png
index 93767660..c867fe6 100644
--- a/docs/html/design/media/principles_error.png
+++ b/docs/html/design/media/principles_error.png
Binary files differ
diff --git a/docs/html/design/media/principles_information_when_need_it.png b/docs/html/design/media/principles_information_when_need_it.png
index c5ef3ca..d78d5c5 100644
--- a/docs/html/design/media/principles_information_when_need_it.png
+++ b/docs/html/design/media/principles_information_when_need_it.png
Binary files differ
diff --git a/docs/html/design/media/principles_keep_it_brief.png b/docs/html/design/media/principles_keep_it_brief.png
index 9c2813b..ee7dbbb 100644
--- a/docs/html/design/media/principles_keep_it_brief.png
+++ b/docs/html/design/media/principles_keep_it_brief.png
Binary files differ
diff --git a/docs/html/design/media/principles_never_lose_stuff.png b/docs/html/design/media/principles_never_lose_stuff.png
index acbefea..84037d9 100644
--- a/docs/html/design/media/principles_never_lose_stuff.png
+++ b/docs/html/design/media/principles_never_lose_stuff.png
Binary files differ
diff --git a/docs/html/design/media/tabs_youtube.png b/docs/html/design/media/tabs_youtube.png
index 69e9268..4ea6c1c 100644
--- a/docs/html/design/media/tabs_youtube.png
+++ b/docs/html/design/media/tabs_youtube.png
Binary files differ
diff --git a/docs/html/design/media/themes_holo_dark.png b/docs/html/design/media/themes_holo_dark.png
index 0a5876a..e1f4477 100644
--- a/docs/html/design/media/themes_holo_dark.png
+++ b/docs/html/design/media/themes_holo_dark.png
Binary files differ
diff --git a/docs/html/design/media/themes_holo_inverse.png b/docs/html/design/media/themes_holo_inverse.png
index 50be4fb..528d119 100644
--- a/docs/html/design/media/themes_holo_inverse.png
+++ b/docs/html/design/media/themes_holo_inverse.png
Binary files differ
diff --git a/docs/html/design/media/themes_holo_light.png b/docs/html/design/media/themes_holo_light.png
index edc7f77..4f34bb3 100644
--- a/docs/html/design/media/themes_holo_light.png
+++ b/docs/html/design/media/themes_holo_light.png
Binary files differ
diff --git a/docs/html/design/media/ui_overview_notifications.png b/docs/html/design/media/ui_overview_notifications.png
index bc0513f..fe4375e 100644
--- a/docs/html/design/media/ui_overview_notifications.png
+++ b/docs/html/design/media/ui_overview_notifications.png
Binary files differ
diff --git a/docs/html/design/patterns/accessibility.jd b/docs/html/design/patterns/accessibility.jd
new file mode 100644
index 0000000..a41397f
--- /dev/null
+++ b/docs/html/design/patterns/accessibility.jd
@@ -0,0 +1,61 @@
+page.title=Accessibility
+@jd:body
+
+<p>One of Android's missions is to organize the world's information and make it universally accessible and useful. Accessibility is the measure of how successfully a product can be used by people with varying abilities. Our mission applies to all users-including people with disabilities such as visual impairment, color deficiency, hearing loss, and limited dexterity.</p>
+<p><a href="https://www.google.com/#hl=en&q=universal+design&fp=1">Universal design</a> is the practice of making products that are inherently accessible to all users, regardless of ability. The Android design patterns were created in accordance with universal design principles, and following them will help your app meet basic usability standards. Adhering to universal design and enabling Android's accessibility tools will make your app as accessible as possible.</p>
+<p>Robust support for accessibility will increase your app's user base. It may also be required for adoption by some organizations.</p>
+<p><a href="http://www.google.com/accessibility/">Learn more about Google and accessibility.</a></p>
+
+<h2 id="tools">Android's Accessibility Tools</h2>
+<p>Android includes several features that support access for users with visual impairments; they don't require drastic visual changes to your app.</p>
+
+<ul>
+  <li><strong><a href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a></strong> is a pre-installed screen reader service provided by Google. It uses spoken feedback to describe the results of actions such as launching an app, and events such as notifications.</li>
+  <li><strong>Explore by Touch</strong> is a system feature that works with TalkBack, allowing you to touch your device's screen and hear what's under your finger via spoken feedback. This feature is helpful to users with low vision.</li>
+  <li><strong>Accessibility settings</strong> let you modify your device's display and sound options, such as increasing the text size, changing the speed at which text is spoken, and more.</li>
+</ul>
+
+<p>Some users use hardware or software directional controllers (such as a D-pad, trackball, keyboard) to jump from selection to selection on a screen. They interact with the structure of your app in a linear fashion, similar to 4-way remote control navigation on a television.</p>
+
+<h2 id="tools">Guidelines</h2>
+<p>The Android design principle "I should always know where I am" is key for accessibility concerns. As a user navigates through an application, they need feedback and a mental model of where they are. All users benefit from a strong sense of information hierarchy and an architecture that makes sense. Most users benefit from visual and haptic feedback during their navigation (such as labels, colors, icons, touch feedback) Low vision users benefit from explicit verbal descriptions and large visuals with high contrast.</p>
+<p>As you design your app, think about the labels and notations needed to navigate your app by sound. When using Explore by Touch, the user enables an invisible but audible layer of structure in your application. Like any other aspect of app design, this structure can be simple, elegant, and robust. The following are Android's recommended guidelines to enable effective navigation for all users.</p>
+
+<h4>Make navigation intuitive</h4>
+<p>Design well-defined, clear task flows with minimal navigation steps, especially for major user tasks. Make sure those tasks are navigable via focus controls. </p>
+
+<h4>Use recommended touch target sizes</h4>
+<p>48 dp is the recommended touch target size for on screen elements. Read about <a href="{@docRoot}design/style/metrics-grids.html">Android Metrics and Grids</a> to learn about implementation strategies to help most of your users. For certain users, it may be appropriate to use larger touch targets. An example of this is educational apps, where buttons larger than the minimum recommendations are appropriate for children with developing motor skills and people with manual dexterity challenges.</p>
+
+
+<h4>Label visual UI elements meaningfully</h4>
+<p>In your wireframes, <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">label functional UI components</a> that have no visible text. Those components might be buttons, icons, tabs with icons, and icons with state (like stars). Developers can use the <code><a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">contentDescription</a></code> attribute to set the label.</p>
+
+<img src="{@docRoot}design/media/accessibility_contentdesc.png">
+
+<h4>Provide alternatives to affordances that time out</h4>
+<p>Your app may have icons or controls that disappear after a certain amount of time. For example, five seconds after starting a video, playback controls may fade from the screen.</p>
+
+<p>Due to the way that TalkBack works, those controls are not read out loud unless they are focused on. If they fade out from the screen quickly, your user may not even be aware that they are available. Therefore, make sure that you are not relying on timed out controls for high priority task flows. (This is a good universal design guideline too.) If the controls enable an important function, make sure that the user can turn on the controls again and/or their function is duplicated elsewhere. You can also change the behavior of your app when accessibility services are turned on. Your developer may be able to make sure that timed-out controls won't disappear.</p>
+
+<h4>Use standard framework controls or enable TalkBack for custom controls</h4>
+<p>Standard Android framework controls work automatically with accessibility services and have ContentDescriptions built in by default.</p>
+
+<p>An oft-overlooked system control is font size. Users can turn on a system-wide large font size in Settings; using the default system font size in your application will enable the user's preferences in your app as well. To enable system font size in your app, mark text and their associated containers to be measured in <a href="{@docRoot}guide/practices/screens_support.html#screen-independence">scale pixels</a>.</p>
+
+<p>Also, keep in mind that when users have large fonts enabled or speak a different language than you, their type might be larger than the space you've allotted for it. Read <a href="{@docRoot}design/style/devices-displays.html">Devices and Displays</a> and <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple Screens</a> for design strategies.</p>
+
+<p>If you use custom controls, Android has the developer tools in place to allow adherence to the above guidelines and provide meaningful descriptions about the UI. Provide adequate notation on your wireframes and direct your developer to the <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#custom-views">Custom Views</a> documentation.</p>
+
+<h4>Try it out yourself</h4>
+<p>Turn on the TalkBack service in <strong>Settings > Accessibility</strong> and navigate your application using directional controls or eyes-free navigation.</p>
+
+<h2>Checklist</h2>
+<ul>
+  <li>Make navigation intuitive</li>
+  <li>Use recommended touch target sizes</li>
+  <li>Label visual UI elements meaningfully</li>
+  <li>Provide alternatives to affordances that time out</li>
+  <li>Use standard framework controls or enable TalkBack for custom controls</li>
+  <li>Try it out yourself</li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index 4206301..80aa77d 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -66,7 +66,7 @@
         <p>
 
 Show the most important actions of your app in the actions section. Actions that don't fit in the
-action bar are moved automatically to the action overflow.
+action bar are moved automatically to the action overflow. Long-press on an icon to view the action's name.
 
         </p>
       </li>
@@ -144,28 +144,44 @@
 <p>For more information, refer to the <a href="{@docRoot}design/patterns/selection.html">Selection
 pattern</a>.</p>
 
-<h2 id="elements">Action Bar Elements</h2>
+<h2 id="elements">View Controls</h2>
+<p>If your app displays data in different views, the action bar has three different controls to allow users to switch between them: tabs, spinners, and drawers.</p>
 
 <h4>Tabs</h4>
-<p><em>Tabs</em> display app views concurrently and make it easy to explore and switch between them. Use tabs
-if you expect your users to switch views frequently.</p>
+<p><em>Tabs</em> display app views concurrently and make it easy to explore and switch between them. Tabs may be fixed, where all tabs are simultaneously displayed, or may scroll, allowing a larger number of views to be presented.</p>
 
 <img src="{@docRoot}design/media/tabs_youtube.png">
 
-<p>There are two types of tabs: fixed and scrollable.</p>
+<p><strong>Use tabs if</strong>:</p>
+<ul>
+<li>You expect your app's users to switch views frequently.</li>
+<li>You want the user to be highly aware of the alternate views.</li>
+</ul>
 
+<h4>Fixed tabs</h4>
 <div class="layout-content-row">
   <div class="layout-content-col span-6">
+<p><em>Fixed tabs</em> are always visible on the screen, and can't be moved out of the way like scrollable
+tabs. Fixed tabs in the main action bar can move to the top bar when the screen orientation changes.</p>
+
+<p>Use fixed tabs to support quick changes between two or three app views. Fixed tabs should always allow the user to navigate between the views by swiping left or right on the content area.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/action_bar_pattern_default_tabs.png">
+    <div class="figure-caption">
+      Default fixed tabs shown in Holo Dark &amp; Light.
+    </div>
+
+  </div>
+</div>
 
 <h4>Scrollable tabs</h4>
-<p><em>Scrollable tabs</em> always take up the entire width of the bar, with the currently active view item in
-the center, and therefore need to live in a dedicated bar. Scrollable tabs can themselves be
-scrolled horizontally to bring more tabs into view.</p>
-<p>Use scrollable tabs if you have a large number of views or if you're unsure how many views will be
-displayed because your app inserts views dynamically (for example, open chats in a messaging app
-that the user can navigate between). Scrollable tabs should always allow the user to navigate
-between the views by swiping left or right on the content area as well as swiping the tabs
-themselves.</p>
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+<p><em>Scrollable tabs</em> always take up the entire width of the bar, with the currently active view item in the center, and therefore need to live in a dedicated bar. Scrollable tabs can themselves be scrolled horizontally to bring more tabs into view.</p>
+<p>Use scrollable tabs if you have a large number of views or if you're unsure how many views will be displayed because your app inserts views dynamically (for example, open chats in a messaging app that the user can navigate between). Scrollable tabs should always allow the user to navigate between the views by swiping left or right on the content area as well as swiping the tabs themselves.</p>
 
   </div>
   <div class="layout-content-col span-7">
@@ -186,30 +202,12 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-6">
 
-<h4>Fixed tabs</h4>
-<p><em>Fixed tabs</em> are always visible on the screen, and can't be moved out of the way like scrollable
-tabs. Fixed tabs in the main action bar can move to the top bar when the screen orientation changes.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="{@docRoot}design/media/action_bar_pattern_default_tabs.png">
-    <div class="figure-caption">
-      Default fixed tabs shown in Holo Dark &amp; Light.
-    </div>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
 <h4>Spinners</h4>
 <p>A <em>spinner</em> is a drop-down menu that allows users to switch between views of your app. </p>
-<p><strong>Use spinners rather than tabs in the main action bar if</strong>:</p>
+<p><strong>Use a spinner in the main action bar if</strong>:</p>
 <ul>
 <li>You don't want to give up the vertical screen real estate for a dedicated tab bar.</li>
-<li>You expect your app's users to switch views infrequently.</li>
+<li>The user is switching between views of the same data set (for example: calendar events viewed by day, week, or month) or data sets of the same type (such as content for two different accounts).</li>
 </ul>
 
   </div>
@@ -223,7 +221,24 @@
   </div>
 </div>
 
-<h4>Action buttons</h4>
+<h4>Drawers</h4>
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+<p>A <em>drawer</em> is a slide-out menu that allows users to switch between views of your app. It can be opened by touching the action bar's app icon (decorated with the Up caret.) Because it relies on Up navigation, a drawer is only suitable for use at the topmost level of your app's hierarchy.</p>
+
+<p><strong>Open a drawer from the main action bar if</strong>:</p>
+<ul>
+<li>You don't want to give up the vertical screen real estate for a dedicated tab bar.</li>
+<li>You want to provide direct navigation to a number of views within your app which don't have direct relationships between each other.</li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-7">
+    <img src="{@docRoot}design/media/actionbar_drawer.png">
+  </div>
+</div>
+
+<h2>Action buttons</h2>
 <p><em>Action buttons</em> on the action bar surface your app's most important activities. Think about which
 buttons will get used most often, and order them accordingly. Depending on available screen real
 estate, the system shows your most important actions as action buttons and moves the rest to the
diff --git a/docs/html/design/patterns/app-structure.jd b/docs/html/design/patterns/app-structure.jd
index e2398ed..a483522 100644
--- a/docs/html/design/patterns/app-structure.jd
+++ b/docs/html/design/patterns/app-structure.jd
@@ -185,28 +185,18 @@
 in a category view.</p>
 <h2 id="details">Details</h2>
 
-<p>The detail view allows you to view and act on your data. The layout of the detail view depends on
-the data type being displayed, and therefore differs widely among apps.</p>
+<p>The detail view allows you to view and act on your data. The layout of the detail view depends on the data type being displayed, and therefore differs widely among apps.</p>
 
 <div class="layout-content-row">
   <div class="layout-content-col span-4">
 
 <h4>Layout</h4>
-<p>Consider the activities people will perform in the detail view and arrange the layout accordingly.
-For immersive content, make use of the lights-out mode to allow for distraction-free viewing of
-full-screen content.</p>
-
-    <img src="{@docRoot}design/media/app_structure_people_detail.png">
+<p>Consider the activities people will perform in the detail view and arrange the layout accordingly.</p>
 
   </div>
   <div class="layout-content-col span-9">
 
-    <img src="{@docRoot}design/media/app_structure_book_detail_page_flip.png">
-    <div class="figure-caption">
-      Google Books' detail view is all about replicating the experience of reading an actual book.
-      The page-flip animation reinforces that notion. To create an immersive experience the app
-      enters lights-out mode, which hides all system UI affordances.
-    </div>
+    <img src="{@docRoot}design/media/app_structure_people_detail.png">
 
     <div class="figure-caption">
       The purpose of the People app's detail view is to surface communication options. The list view
@@ -217,9 +207,25 @@
   </div>
 </div>
 
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Lights-out mode</h4>
+<p>Immersive content like media and games is best experienced full screen without distractions. But that doesn't mean you can't also offer actions on the content like sharing, commenting, or searching. If the user hasn't interacted with any of the controls after a short period of time, automatically fade away the action bar and all system UI affordances so the user can lean back and enjoy the content. We call this lights-out mode. Later, if the user wants to take some action, they can touch anywhere on the screen to exit lights-out mode and bring back the controls.</p>
+
+  </div>
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/app_structure_book_detail_page_flip.png">
+    <div class="figure-caption">
+      Google Books' detail view replicates the immersive experience of reading an actual book through lights-out mode and a page-flip animation.
+    </div>
+  </div>
+</div>
+
 <h4>Make navigation between detail views efficient</h4>
 <p>If your users are likely to want to look at multiple items in sequence, allow them to navigate
-between items from within the detail view. Use swipe views or other techniques, such as filmstrips,
+between items from within the detail view. Use swipe views or other techniques, such as thumbnail view controls,
 to achieve this.</p>
 
 <img src="{@docRoot}design/media/app_structure_gmail_swipe.png">
@@ -229,8 +235,8 @@
 
 <img src="{@docRoot}design/media/app_structure_gallery_filmstrip.png">
 <div class="figure-caption">
-  In addition to supporting swipe gestures to move left or right through images, Gallery provides a
-  filmstrip control that lets people quickly jump to specific images.
+  In addition to supporting swipe gestures to move left or right through pages, Magazines provides a
+  thumbnail view control that lets people quickly jump to specific pages.
 </div>
 
 <h2 id="checklist">Checklist</h2>
diff --git a/docs/html/design/patterns/help.jd b/docs/html/design/patterns/help.jd
new file mode 100644
index 0000000..4a92c7b
--- /dev/null
+++ b/docs/html/design/patterns/help.jd
@@ -0,0 +1,114 @@
+page.title=Help
+@jd:body
+
+<p>We wish we could guarantee that if you follow every piece of advice on this website, everyone will be able to learn and use your app without a hitch. Sadly, that's not the case.</p>
+
+<p>Some of your users will run into questions or problems along the way. They'll be looking for answers <strong>within your app</strong>, and if they don't find them quickly, they may leave and never come back.</p>
+
+<p>This page covers design patterns for making help accessible in your app and tips for creating help content for users who are eager for assistance.</p>
+
+<h2 id="your-app">Designing Help into Your App</h2>
+
+<h3>Don't show unsolicited help, except in very limited cases</h3>
+<p>Naturally, you want everyone to quickly learn the ropes, discover the cool features, and get the most out of your app. So you might be tempted to present a one-time introductory slideshow, video, or splash screen to all new users when they first open the app. Or you might be drawn to the idea of displaying helpful text bubbles or dialogs when users interact with certain features for the first time.</p>
+<p>In almost all cases, we advise <strong>against</strong> approaches like these because:</p>
+<ul>
+  <li><strong>They're interruptions.</strong> People will be eager to start using your app, and anything you put in front of them will feel like an obstacle or possibly an annoyance, despite your good intentions. And because they didn't ask for it, they probably won't pay close attention to it.</li>
+  <li><strong>They're usually not necessary.</strong> If you have usability concerns about an aspect of your app, don't just throw help at the problem. Try to solve it in the UI. Apply Android design patterns, styles, and building blocks, and you'll go a long way in reducing the need to educate your users.</li>
+</ul>
+<p>The only reason for showing pure help content to new users unsolicited is:<br>
+<em>To teach high value functionality that's only available through an atypical use of a gesture.</em></p>
+
+<p>For example, we use help content to teach users how to place apps on their Home Screen. This functionality is:</p>
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+    <ol>
+      <li><strong>High value</strong>
+      <p>Without it, users wouldn't be able to customize the most frequently-visited Android screen to meet their needs.</p></li>
+      <li><strong>Available only through a gesture</strong>
+      <p>Users can't do this through a button or a menu.</p></li>
+      <li><strong>Atypical for the gesture</strong>
+      <p>Many high value functions invoked through a gesture - like scrolling, swiping tabs, and turning pages - are common and yield expected results. Users will be able to discover them in your app, and unsolicited help is unnecessary. But here, the gesture does something unexpected: press and hold doesn't just select an app, it also immediately navigates to the Home Screen and creates a shortcut to the app that can then be dragged around.</p></li>
+    </ol>
+    <p>However, this is an exceptional case. Most functionality doesn't meet all three of these criteria.</p>
+  </div>
+  <div class="layout-content-col span-5">
+    <img src="{@docRoot}design/media/help_cling.png">
+    <div class="figure-caption">
+      The first time each user visits the All Apps screen, a semi-transparent overlay appears to teach an important gesture.
+    </div>
+  </div>
+  <p class="clearfix">Bottom line: when it comes to offering help in your app, it's much better to <strong>let users come to you</strong> when they need it.</p>
+</div>
+
+<h3 id="standard-design">Follow the standard design for navigating to help</h3>
+
+<p>On every screen in your app, offer help in the <a href="{@docRoot}design/patterns/actionbar.html">action overflow</a>. Always make it the very last item in the menu and label it "Help".</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+    <img src="{@docRoot}design/media/help_overflow.png">
+  </div>
+  <div class="layout-content-col span-6">
+    <img src="{@docRoot}design/media/help_solo_overflow.png">
+    <div class="figure-caption">
+      Even if your screen has no other action overflow items, "Help" should appear there and not be promoted to the action bar.
+    </div>
+  </div>
+  <p>We've established this standard design so that when users are desperate for help, they won't have to hunt to find it (see design principle: <a href="{@docRoot}design/get-started/principles.html#give-me-tricks">Give me tricks that work everywhere</a>).</p>
+</div>
+
+<h3 id="help-urgent">Assume that every call for help is urgent</h3>
+
+<p>In addition to help, you might want to expose miscellaneous other information, such as copyright info, credits, terms of service, and privacy policy.</p>
+
+<p>Let users access this information through your Help menu item, but don't give it prominence equal to the core help content. Optimize the flow for people who have urgent questions about how to do something or why something is happening in your app. The smaller subset of users who are looking for legal fine print or the names of the people who created the app won't be as burdened by taking a few extra steps.</p>
+
+<p>The same is true for any communication options you might want to provide, such as contacting customer support or submitting feedback. Offer these options in a way that doesn't add an extra step before users see help. When you put the help content forward, you increase the likelihood that users will find the answers on their own, which in turn reduces your support costs.</p>
+
+<p>When someone chooses "Help":</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+    <img src="{@docRoot}design/media/help_dont.png">
+  </div>
+  <div class="layout-content-col span-4">
+    <img src="{@docRoot}design/media/help_better.png">
+  </div>
+  <div class="layout-content-col span-5">
+    <img src="{@docRoot}design/media/help_evenbetter.png">
+  </div>  
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+    <h4 class="do-dont-label bad">Don't</h4>
+    <p>Present a dialog asking them to choose between help and other options.</p>
+  </div>
+  <div class="layout-content-col span-4">
+    <h4 class="do-dont-label good">Better</h4>
+    <p>Immediately launch a web browser with help content. Place other options in a footer.</p>
+  </div>
+  <div class="layout-content-col span-5">
+    <h4 class="do-dont-label good">Even Better</h4>
+    <p>Build a help screen in your app and offer other options in the action bar.</p>
+    <p>This requires more development work than launching a web browser, but it's a nicer experience for users because they don't leave your app to get the help they need and doesn't require a network connection.</p>
+  </div>
+</div>
+
+<h2>Principles for Writing On-Screen Help Content</h2>
+
+<h4>Help is part of the UI</h4>
+<p>On-screen help is an extension of your app's UI, not a description of it. All words on the screen from the core app to the help should follow our <a href="{@docRoot}design/style/writing.html">Writing Style</a> principles so that the end-to-end experience feels seamless and cohesive.</p>
+
+<h4>Make every pixel count</h4>
+<p>It's not necessary to document every single detail about your app, especially things that are extremely apparent just by looking at the UI, or behaviors that are standard for the platform. Surface just the key additional information that the on-screen text doesn't have room to describe, in a way that makes it easy to map to the screen.</p>
+
+<h4>Pictures are faster than words</h4>
+<p>In describing key UI elements and providing step-by-step instructions, consider combining text with icons, partial screenshots with callouts, and other imagery. You'll need fewer words to explain things, and users will absorb the information more quickly.</p>
+
+<h4>Help me scan, not read</h4>
+<p>People don't read help from start to finish. They scan around, looking for a piece of information containing the answer they need. Make it less burdensome with friendly formatting and layout choices like bold headings, bulleted and numbered lists, tables, and white space between paragraphs. And if you have a large amount of content, divide it into multiple screens to cut down on scrolling.</p>
+
+<h4>Take me straight to the answer</h4>
+<p>What's better than a screen that's easy to scan? A screen that requires no scanning at all because the answer's right there. Consider having each screen in your app navigate to help that's relevant just to that screen. We call this <em>contextual help</em>, and it's the holy grail of user assistance. If you take this approach, be sure to also provide a way to get to the rest of the help content.</p>
\ No newline at end of file
diff --git a/docs/html/design/patterns/multi-pane-layouts.jd b/docs/html/design/patterns/multi-pane-layouts.jd
index 0e63e32..f752be2 100644
--- a/docs/html/design/patterns/multi-pane-layouts.jd
+++ b/docs/html/design/patterns/multi-pane-layouts.jd
@@ -26,8 +26,8 @@
 relationship between the panels.</p>
 <h2 id="orientation">Compound Views and Orientation Changes</h2>
 
-<p>Screens should have the same functionality regardless of orientation. If you use a compound view in
-one orientation, don't split it up when the user rotates the screen. There are several techniques
+<p>Screens should strive to have the same functionality regardless of orientation. If you use a compound view in
+one orientation, try not to split it up when the user rotates the screen. There are several techniques
 you can use to adjust the layout after orientation change while keeping functional parity intact.</p>
 
 <div class="layout-content-row">
@@ -83,9 +83,7 @@
   <div class="layout-content-col span-5">
 
 <h4>Show/hide</h4>
-<p>After rotating the device, show the right pane in fullscreen view. Use the Up icon in the action bar
-to show the left panel and allow navigation to a different email. Hide the left panel by touching
-the content in the detail panel.</p>
+<p>If your screen cannot accommodate the compound view on rotation show the right pane in full screen view on rotation to portrait. Use the Up icon in action bar to show the parent screen.</p>
 
   </div>
 </div>
@@ -104,7 +102,7 @@
 <p>Look for opportunities to consolidate your views into multi-panel compound views.</p>
 </li>
 <li>
-<p>Make sure that your screens provide functional parity after the screen orientation
+<p>Make sure that your screens try to provide functional parity after the screen orientation
   changes.</p>
 </li>
 </ul>
diff --git a/docs/html/design/patterns/notifications.jd b/docs/html/design/patterns/notifications.jd
index ad88a01..fbb05e3 100644
--- a/docs/html/design/patterns/notifications.jd
+++ b/docs/html/design/patterns/notifications.jd
@@ -1,11 +1,164 @@
 page.title=Notifications
 @jd:body
 
-<p>The notification system allows your app to keep the user informed about important events, such as
-new messages in a chat app or a calendar event.</p>
-<p>To create an app that feels streamlined, pleasant, and respectful, it is important to design your
-notifications carefully. Notifications embody your app's voice, and contribute to your app's
-personality. Unwanted or unimportant notifications can annoy the user, so use them judiciously.</p>
+<p>The notification system allows your app to keep the user informed about events, such as new chat messages or a calendar event. Think of notifications as a news channel that alerts the user to important events as they happen or a log that chronicles events while the user is not paying attention.</p>
+
+<h4>New in Jelly Bean</h4>
+<p>In Jelly Bean, notifications received their most important structural and functional update since the beginning of Android.</p>
+<ul>
+  <li>Notifications can include actions that enable the user to immediately act on a notification from the notification drawer.</li>
+  <li>Notifications are now more flexible in size and layout.</li>
+  <li>Stacked notifications can be collapsed and expanded.</li>
+  <li>A priority flag was introduced that helps to sort notifications by importance rather than time only.</li>
+</ul>
+
+<h2>Anatomy of a notification</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+    <h4>Base Layout</h4>
+    <p>At a minimum, all notifications consist of a base layout, including:</p>
+    <ul>
+      <li>the sending application's notification icon or the sender's photo</li>
+      <li>a notification title and message</li>
+      <li>an optional timestamp</li>
+      <li>a secondary icon to identify the sending application when the sender's image is shown for the main icon</li>
+    </ul>
+    <p>The base notification layout has not changed in Jelly Bean, so app notifications designed for versions earlier than Jelly Bean still look and work the same.</p>
+  </div>
+  <div class="layout-content-col span-6">
+    <img src="{@docRoot}design/media/notifications_pattern_anatomy.png">
+    <div class="figure-caption">
+      Base layout of a notification
+    </div>
+  </div>
+</div>
+
+<h4>Expanded layouts</h4>
+<p>With Jelly Bean you have the option to provide more event detail. You can use this to show the first few lines of a message or show a larger image preview. This provides the user with additional context, and - in some cases - may allow the user to read a message in its entirety.  The user can pinch-zoom or two-finger glide in order to toggle between base and expanded layouts. For single event notifications, Android provides two expanded layout templates (text and image) for you to re-use in your application.</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_expandable.png">
+
+<h4>Actions</h4>
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+    <p>Starting with Jelly Bean, Android supports optional actions that are displayed at the bottom of the notification. With actions, users can handle the most common tasks for a particular notification from within the notification shade without having to open the originating application. This speeds up interaction and, in conjunction with "swipe-to-dismiss", helps users to streamline their notification triaging experience.</p>
+    <p>Be judicious with how many actions you include with a notification. The more actions you include, the more cognitive complexity you create. Limit yourself to the fewest number of actions possible by only including the most imminently important and meaningful ones.</p>
+    <p>Good candidates for actions on notifications are actions that are:</p>
+    <ul>
+      <li>essential, frequent and typical for the content type you're displaying</li>
+      <li>time-critical</li>
+      <li>not overlapping with neighboring actions</li>
+    </ul>
+    <p>Avoid actions that are:</p>
+    <ul>
+      <li>ambiguous</li>
+      <li>implicit to the default action of the notification (such as "Read" or "Open")</li>
+    </ul>
+  </div>
+  <div class="layout-content-col span-7">
+    <img src="{@docRoot}design/media/notifications_pattern_two_actions.png">
+    <div class="figure-caption">
+      Calendar reminder notification with two actions
+    </div>
+  </div>
+</div>
+
+<p>You can specify a maximum of three actions, each consisting of an action icon and an action name. Adding actions to a base layout will make the notification expandable, even if the notification doesn't have an expanded layout. Since actions are only shown for expanded notifications and are otherwise hidden, you must make sure that any action a user can invoke from a notification is available from within the associated application as well.</p>
+
+<h2>Design guidelines</h2>
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+    <img src="{@docRoot}design/media/notifications_pattern_personal.png">
+  </div>
+  <div class="layout-content-col span-7">
+    <h4>Make it personal</h4>
+    <p>For notifications of items sent by another user (such as a message or status update), include that person's image.</p>
+    <p>Remember to include the app icon as a secondary icon in the notification, so that the user can still identify which app posted it.</p>
+  </div>
+</div>
+
+<h4>Navigate to the right place</h4>
+<p>When the user touches a notification, open your app to the place where the user can consume and
+act upon the data referenced in the notification. In most cases this will be the detail view of a
+single data item such as a message, but it might also be a summary view if the notification is
+stacked (see <em>Stacked notifications</em> below) and references multiple items. If in any of those cases
+the user is taken to a hierarchy level below your app's top-level, insert navigation into your app's
+back stack to allow them to navigate to your app's top level using the system back key. For more
+information, see the chapter on <em>System-to-app navigation</em> in the
+<a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design pattern.</p>
+<h4>Timestamps for time sensitive events</h4>
+<p>By default, standard Android notifications include a timestamp. Consider
+whether the timestamp is valuable in the context of your notification.</p>
+<p>Include a timestamp if the user likely needs to know how long ago the notification occurred. Good
+candidates for timestamps include communication notifications (email, messaging, chat, voicemail)
+where the user may need the timestamp information to understand the context of a message or to
+tailor a response.</p>
+
+<h4>Correctly set and manage notification priority</h4>
+<p>Starting with Jelly Bean, Android now supports a priority flag for notifications. It allows you to influence where your notification will appear in comparison to other notifications and help to make sure that users always see their most important notifications first. You can choose from the following priority levels when posting a notification:</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_priority.png">
+
+<table>
+  <tr>
+    <th><strong>Priority</strong></th>
+    <th><strong>Use</strong></th>
+  </tr>
+  <tr>
+    <td>MAX</td>
+    <td>Use for critical and urgent notifications that alert the user to a condition that is time-critical or needs to be resolved before they can continue with a particular task.</td>
+  </tr>
+  <tr>
+    <td>HIGH</td>
+    <td>Use high priority notifications primarily for important communication, such as message or chat events with content that is particularly interesting for the user.</td>
+  </tr>
+  <tr>
+    <td>DEFAULT</td>
+    <td>The default priority. Keep all notifications that don't fall into any of the other categories at this priority level.</td>
+  </tr>
+  <tr>
+    <td>LOW</td>
+    <td>Use for notifications that you still want the user to be informed about, but that rate low in urgency.</td>
+  </tr>
+  <tr>
+    <td>MIN</td>
+    <td>Contextual/background information (e.g. weather information, contextual location information). Minimum     priority notifications will not show in the status bar. The user will only discover them when they expand the notification tray.</td>
+  </tr>
+</table>
+
+<h4>Stack your notifications</h4>
+<p>If your app creates a notification while another of the same type is still pending, avoid creating
+an altogether new notification object. Instead, stack the notification.</p>
+<p>A stacked notification builds a summary description and allows the user to understand how many
+notifications of a particular kind are pending.</p>
+<p><strong>Don't</strong>:</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_additional_fail.png">
+
+<p><strong>Do</strong>:</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_additional_win.png">
+
+<p>You can provide more detail about the individual notifications that make up a stack by using the expanded digest layout. This allows users to gain a better sense of which notifications are pending and if they are interesting enough to be read in detail within the associated app.</p>
+
+<img src="{@docRoot}design/media/notifications_expand_contract_msg.png">
+
+<h4>Make notifications optional</h4>
+<p>Users should always be in control of notifications. Allow the user to silence the notifications from
+your app by adding a notification settings item to your application settings.</p>
+<h4>Use distinct icons</h4>
+<p>By glancing at the notification area, the user should be able to discern what notification types are
+currently pending.</p>
+<p><strong>Do</strong>:</p>
+<p>Look at the notification icons the Android apps already provide and create notification icons for
+  your app that are sufficiently distinct in appearance.</p>
+<p><strong>Don't</strong>:</p>
+<p>Use color to distinguish your app from others. Notification icons should be <a href="{@docRoot}design/style/iconography.html#notification">white</a>.</p>
+
+<h2>Building notifications that users care about</h2>
+<p>To create an app that feels streamlined, pleasant, and respectful, it is important to design your notifications carefully. Notifications embody your app's voice, and contribute to your app's personality. Unwanted or unimportant notifications can annoy the user, so use them judiciously.</p>
+
 <h4>When to display a notification</h4>
 <p>To create an application that people love, it's important to recognize that the user's attention and
 focus is a resource that must be protected. To use an analogy that might resonate with software
@@ -66,108 +219,10 @@
 
   </div>
   <div class="layout-content-col span-6">
-
     <img src="{@docRoot}design/media/notifications_pattern_social_fail.png">
-
   </div>
 </div>
 
-<h2 id="design-guidelines">Design Guidelines</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="{@docRoot}design/media/notifications_pattern_anatomy.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Make it personal</h4>
-<p>For notifications of items sent by another user (such as a message or status update), include that
-person's image.</p>
-<p>Remember to include the app icon as a secondary icon in the notification, so that the user can
-still identify which app posted it.</p>    
-
-  </div>
-</div>
-
-<h4>Navigate to the right place</h4>
-<p>When the user touches a notification, be open your app to the place where the user can consume and
-act upon the data referenced in the notification. In most cases this will be the detail view of a
-single data item (e.g. a message), but it might also be a summary view if the notification is
-stacked (see <em>Stacked notifications</em> below) and references multiple items. If in any of those cases
-the user is taken to a hierarchy level below your app's top-level, insert navigation into your app's
-back stack to allow them to navigate to your app's top level using the system back key. For more
-information, see the chapter on <em>System-to-app navigation</em> in the
-<a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design pattern.</p>
-<h4>Timestamps for time sensitive events</h4>
-<p>By default, standard Android notifications include a timestamp in the upper right corner. Consider
-whether the timestamp is valuable in the context of your notification. If the timestamp is not
-valuable, consider if the event is important enough to warrant grabbing the user's attention with a
-notification. If the notification is important enough, decide if you would like to opt out of
-displaying the timestamp.</p>
-<p>Include a timestamp if the user likely needs to know how long ago the notification occurred. Good
-candidates for timestamps include communication notifications (email, messaging, chat, voicemail)
-where the user may need the timestamp information to understand the context of a message or to
-tailor a response.</p>
-<h4>Stack your notifications</h4>
-<p>If your app creates a notification while another of the same type is still pending, avoid creating
-an altogether new notification object. Instead, stack the notification.</p>
-<p>A stacked notification builds a summary description and allows the user to understand how many
-notifications of a particular kind are pending.</p>
-<p><strong>Don't</strong>:</p>
-
-<img src="{@docRoot}design/media/notifications_pattern_additional_fail.png">
-
-<p><strong>Do</strong>:</p>
-
-<img src="{@docRoot}design/media/notifications_pattern_additional_win.png">
-
-<p>If you keep the summary and detail information on different screens, a stacked notification may need
-to open to a different place in the app than a single notification.</p>
-<p>For example, a single email notification should always open to the content of the email, whereas a
-stacked email notification opens to the Inbox view.</p>
-<h4>Clean up after yourself</h4>
-<p>Just like calendar events, some notifications alert the user to an event that happens at a
-particular point in time. After that moment has passed, the notification is likely not important to
-the user anymore, and you should consider removing it automatically.  The same is true for active
-chat conversations or voicemail messages the user has listened to, users should not have to manually
-dismiss notifications independently from taking action on them.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Provide a peek into your notification</h4>
-<p>You can provide a short preview of your notification's content by providing optional ticker text.
-The ticker text is shown for a short amount of time when the notification enters the system and then
-hides automatically.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="{@docRoot}design/media/notifications_pattern_phone_ticker.png">
-
-  </div>
-</div>
-
-<h4>Make notifications optional</h4>
-<p>Users should always be in control of notifications. Allow the user to silence the notifications from
-your app by adding a notification settings item to your application settings.</p>
-<h4>Use distinct icons</h4>
-<p>By glancing at the notification area, the user should be able to discern what notification types are
-currently pending.</p>
-<p><strong>Do</strong>:</p>
-<ul>
-<li>Look at the notification icons the Android apps already provide and create notification icons for
-  your app that are sufficiently distinct in appearance.</li>
-</ul>
-<p><strong>Don't</strong>:</p>
-<ul>
-<li>Use color to distinguish your app from others. Notification icons should generally be monochrome.</li>
-</ul>
-
 <h2 id="interacting-with-notifications">Interacting With Notifications</h2>
 
 <div class="layout-content-row">
diff --git a/docs/html/design/patterns/swipe-views.jd b/docs/html/design/patterns/swipe-views.jd
index 95d65dd..b98a063 100644
--- a/docs/html/design/patterns/swipe-views.jd
+++ b/docs/html/design/patterns/swipe-views.jd
@@ -65,6 +65,9 @@
   the swipe gesture.</p>
 </li>
 <li>
+<p>If a view contains content that exceeds the width of the screen such as a wide Email message, make sure the user's initial swipes will scroll horizontally within the view. Once the end of the content is reached, an additional swipe should navigate to the next view. In addition, support the use of edge swipes to immediately navigate between views when content scrolls horizontally.</p>
+</li>
+<li>
 <p>Consider adding contextual information in your detail view that informs the user about the
   relative list position of the currently visible item.</p>
 </li>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index a32e469..f49c429 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -22,8 +22,9 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
+import java.io.UTFDataFormatException;
 import java.nio.charset.Charsets;
+import java.nio.charset.ModifiedUtf8;
 import java.util.ArrayList;
 
 /**
@@ -75,7 +76,7 @@
     }
 
     public byte[] get(String key) {
-        return get(getBytes(key));
+        return get(getKeyBytes(key));
     }
 
     private boolean put(byte[] key, byte[] value) {
@@ -84,7 +85,7 @@
     }
 
     public boolean put(String key, byte[] value) {
-        return put(getBytes(key), value);
+        return put(getKeyBytes(key), value);
     }
 
     private boolean delete(byte[] key) {
@@ -93,7 +94,7 @@
     }
 
     public boolean delete(String key) {
-        return delete(getBytes(key));
+        return delete(getKeyBytes(key));
     }
 
     private boolean contains(byte[] key) {
@@ -102,7 +103,7 @@
     }
 
     public boolean contains(String key) {
-        return contains(getBytes(key));
+        return contains(getKeyBytes(key));
     }
 
     public byte[][] saw(byte[] prefix) {
@@ -111,13 +112,13 @@
     }
 
     public String[] saw(String prefix) {
-        byte[][] values = saw(getBytes(prefix));
+        byte[][] values = saw(getKeyBytes(prefix));
         if (values == null) {
             return null;
         }
         String[] strings = new String[values.length];
         for (int i = 0; i < values.length; ++i) {
-            strings[i] = toString(values[i]);
+            strings[i] = toKeyString(values[i]);
         }
         return strings;
     }
@@ -133,7 +134,7 @@
     }
 
     public boolean password(String password) {
-        return password(getBytes(password));
+        return password(getPasswordBytes(password));
     }
 
     public boolean lock() {
@@ -147,7 +148,7 @@
     }
 
     public boolean unlock(String password) {
-        return unlock(getBytes(password));
+        return unlock(getPasswordBytes(password));
     }
 
     public boolean isEmpty() {
@@ -161,7 +162,7 @@
     }
 
     public boolean generate(String key) {
-        return generate(getBytes(key));
+        return generate(getKeyBytes(key));
     }
 
     private boolean importKey(byte[] keyName, byte[] key) {
@@ -170,7 +171,7 @@
     }
 
     public boolean importKey(String keyName, byte[] key) {
-        return importKey(getBytes(keyName), key);
+        return importKey(getKeyBytes(keyName), key);
     }
 
     private byte[] getPubkey(byte[] key) {
@@ -179,7 +180,7 @@
     }
 
     public byte[] getPubkey(String key) {
-        return getPubkey(getBytes(key));
+        return getPubkey(getKeyBytes(key));
     }
 
     private boolean delKey(byte[] key) {
@@ -188,7 +189,7 @@
     }
 
     public boolean delKey(String key) {
-        return delKey(getBytes(key));
+        return delKey(getKeyBytes(key));
     }
 
     private byte[] sign(byte[] keyName, byte[] data) {
@@ -197,7 +198,7 @@
     }
 
     public byte[] sign(String key, byte[] data) {
-        return sign(getBytes(key), data);
+        return sign(getKeyBytes(key), data);
     }
 
     private boolean verify(byte[] keyName, byte[] data, byte[] signature) {
@@ -206,7 +207,7 @@
     }
 
     public boolean verify(String key, byte[] data, byte[] signature) {
-        return verify(getBytes(key), data, signature);
+        return verify(getKeyBytes(key), data, signature);
     }
 
     private boolean grant(byte[] key, byte[] uid) {
@@ -215,7 +216,7 @@
     }
 
     public boolean grant(String key, int uid) {
-        return grant(getBytes(key), Integer.toString(uid).getBytes());
+         return grant(getKeyBytes(key), getUidBytes(uid));
     }
 
     private boolean ungrant(byte[] key, byte[] uid) {
@@ -224,7 +225,7 @@
     }
 
     public boolean ungrant(String key, int uid) {
-        return ungrant(getBytes(key), Integer.toString(uid).getBytes());
+        return ungrant(getKeyBytes(key), getUidBytes(uid));
     }
 
     public int getLastError() {
@@ -291,11 +292,34 @@
         return null;
     }
 
-    private static byte[] getBytes(String string) {
-        return string.getBytes(Charsets.UTF_8);
+    /**
+     * ModifiedUtf8 is used for key encoding to match the
+     * implementation of NativeCrypto.ENGINE_load_private_key.
+     */
+    private static byte[] getKeyBytes(String string) {
+        try {
+            int utfCount = (int) ModifiedUtf8.countBytes(string, false);
+            byte[] result = new byte[utfCount];
+            ModifiedUtf8.encode(result, 0, string);
+            return result;
+        } catch (UTFDataFormatException e) {
+            throw new RuntimeException(e);
+        }
     }
 
-    private static String toString(byte[] bytes) {
-        return new String(bytes, Charsets.UTF_8);
+    private static String toKeyString(byte[] bytes) {
+        try {
+            return ModifiedUtf8.decode(bytes, new char[bytes.length], 0, bytes.length);
+        } catch (UTFDataFormatException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static byte[] getPasswordBytes(String password) {
+        return password.getBytes(Charsets.UTF_8);
+    }
+
+    private static byte[] getUidBytes(int uid) {
+        return Integer.toString(uid).getBytes(Charsets.UTF_8);
     }
 }
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 91c56d6..32cd6e2 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -37,7 +37,7 @@
     private static final String TEST_PASSWD2 = "87654321";
     private static final String TEST_KEYNAME = "test-key";
     private static final String TEST_KEYNAME1 = "test-key.1";
-    private static final String TEST_KEYNAME2 = "test-key.2";
+    private static final String TEST_KEYNAME2 = "test-key\02";
     private static final byte[] TEST_KEYVALUE = "test value".getBytes(Charsets.UTF_8);
 
     // "Hello, World" in Chinese
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 2255bf2..38a29d3 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -39,11 +39,11 @@
     boolean providerMeetsCriteria(String provider, in Criteria criteria);
 
     void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance,
-        boolean singleShot, in ILocationListener listener);
+        boolean singleShot, in ILocationListener listener, String packageName);
     void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance,
-        boolean singleShot, in PendingIntent intent);
-    void removeUpdates(in ILocationListener listener);
-    void removeUpdatesPI(in PendingIntent intent);
+        boolean singleShot, in PendingIntent intent, String packageName);
+    void removeUpdates(in ILocationListener listener, String packageName);
+    void removeUpdatesPI(in PendingIntent intent, String packageName);
 
     boolean addGpsStatusListener(IGpsStatusListener listener);
     void removeGpsStatusListener(IGpsStatusListener listener);
@@ -54,13 +54,13 @@
     boolean sendExtraCommand(String provider, String command, inout Bundle extras);
 
     void addProximityAlert(double latitude, double longitude, float distance,
-        long expiration, in PendingIntent intent);
+        long expiration, in PendingIntent intent, String packageName);
     void removeProximityAlert(in PendingIntent intent);
 
     Bundle getProviderInfo(String provider);
     boolean isProviderEnabled(String provider);
 
-    Location getLastKnownLocation(String provider);
+    Location getLastKnownLocation(String provider, String packageName);
 
     // Used by location providers to tell the location manager when it has a new location.
     // Passive is true if the location is coming from the passive provider, in which case
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 1299574..5c256a3 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -17,6 +17,7 @@
 package android.location;
 
 import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Looper;
@@ -160,6 +161,8 @@
      */
     public static final String EXTRA_GPS_ENABLED = "enabled";
 
+    private final Context mContext;
+
     // Map from LocationListeners to their associated ListenerTransport objects
     private HashMap<LocationListener,ListenerTransport> mListeners =
         new HashMap<LocationListener,ListenerTransport>();
@@ -260,8 +263,9 @@
      * right way to create an instance of this class is using the
      * factory Context.getSystemService.
      */
-    public LocationManager(ILocationManager service) {
+    public LocationManager(Context context, ILocationManager service) {
         mService = service;
+        mContext = context;
     }
 
     private LocationProvider createProvider(String name, Bundle info) {
@@ -657,7 +661,8 @@
                     transport = new ListenerTransport(listener, looper);
                 }
                 mListeners.put(listener, transport);
-                mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport);
+                mService.requestLocationUpdates(provider, criteria, minTime, minDistance,
+                        singleShot, transport, mContext.getPackageName());
             }
         } catch (RemoteException ex) {
             Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex);
@@ -837,7 +842,8 @@
         }
 
         try {
-            mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent);
+            mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot,
+                    intent, mContext.getPackageName());
         } catch (RemoteException ex) {
             Log.e(TAG, "requestLocationUpdates: RemoteException", ex);
         }
@@ -1005,7 +1011,7 @@
         try {
             ListenerTransport transport = mListeners.remove(listener);
             if (transport != null) {
-                mService.removeUpdates(transport);
+                mService.removeUpdates(transport, mContext.getPackageName());
             }
         } catch (RemoteException ex) {
             Log.e(TAG, "removeUpdates: DeadObjectException", ex);
@@ -1028,7 +1034,7 @@
             Log.d(TAG, "removeUpdates: intent = " + intent);
         }
         try {
-            mService.removeUpdatesPI(intent);
+            mService.removeUpdatesPI(intent, mContext.getPackageName());
         } catch (RemoteException ex) {
             Log.e(TAG, "removeUpdates: RemoteException", ex);
         }
@@ -1087,7 +1093,7 @@
         }
         try {
             mService.addProximityAlert(latitude, longitude, radius,
-                                       expiration, intent);
+                                       expiration, intent, mContext.getPackageName());
         } catch (RemoteException ex) {
             Log.e(TAG, "addProximityAlert: RemoteException", ex);
         }
@@ -1153,7 +1159,7 @@
             throw new IllegalArgumentException("provider==null");
         }
         try {
-            return mService.getLastKnownLocation(provider);
+            return mService.getLastKnownLocation(provider, mContext.getPackageName());
         } catch (RemoteException ex) {
             Log.e(TAG, "getLastKnowLocation: RemoteException", ex);
             return null;
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 2918dbc..8c1581c 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.database.Cursor;
 import android.location.Address;
 import android.location.Criteria;
@@ -79,6 +80,8 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Observable;
@@ -109,6 +112,9 @@
     private static final String INSTALL_LOCATION_PROVIDER =
         android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
 
+    private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
+    private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
+
     // Location Providers may sometimes deliver location updates
     // slightly faster that requested - provide grace period so
     // we don't unnecessarily filter events that are otherwise on
@@ -193,6 +199,10 @@
 
     private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
 
+    // for prefix blacklist
+    private String[] mWhitelist = new String[0];
+    private String[] mBlacklist = new String[0];
+
     // for Settings change notification
     private ContentQueryMap mSettings;
 
@@ -205,20 +215,23 @@
         final PendingIntent mPendingIntent;
         final Object mKey;
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
+        final String mPackageName;
 
         int mPendingBroadcasts;
         String mRequiredPermissions;
 
-        Receiver(ILocationListener listener) {
+        Receiver(ILocationListener listener, String packageName) {
             mListener = listener;
             mPendingIntent = null;
             mKey = listener.asBinder();
+            mPackageName = packageName;
         }
 
-        Receiver(PendingIntent intent) {
+        Receiver(PendingIntent intent, String packageName) {
             mPendingIntent = intent;
             mListener = null;
             mKey = intent;
+            mPackageName = packageName;
         }
 
         @Override
@@ -601,6 +614,7 @@
 
         // Load providers
         loadProviders();
+        loadBlacklist();
 
         // Register for Network (Wifi or Mobile) updates
         IntentFilter intentFilter = new IntentFilter();
@@ -1110,11 +1124,11 @@
         }
     }
 
-    private Receiver getReceiver(ILocationListener listener) {
+    private Receiver getReceiver(ILocationListener listener, String packageName) {
         IBinder binder = listener.asBinder();
         Receiver receiver = mReceivers.get(binder);
         if (receiver == null) {
-            receiver = new Receiver(listener);
+            receiver = new Receiver(listener, packageName);
             mReceivers.put(binder, receiver);
 
             try {
@@ -1129,10 +1143,10 @@
         return receiver;
     }
 
-    private Receiver getReceiver(PendingIntent intent) {
+    private Receiver getReceiver(PendingIntent intent, String packageName) {
         Receiver receiver = mReceivers.get(intent);
         if (receiver == null) {
-            receiver = new Receiver(intent);
+            receiver = new Receiver(intent, packageName);
             mReceivers.put(intent, receiver);
         }
         return receiver;
@@ -1157,7 +1171,9 @@
     }
 
     public void requestLocationUpdates(String provider, Criteria criteria,
-        long minTime, float minDistance, boolean singleShot, ILocationListener listener) {
+        long minTime, float minDistance, boolean singleShot, ILocationListener listener,
+        String packageName) {
+        checkPackageName(Binder.getCallingUid(), packageName);
         if (criteria != null) {
             // FIXME - should we consider using multiple providers simultaneously
             // rather than only the best one?
@@ -1170,7 +1186,7 @@
         try {
             synchronized (mLock) {
                 requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
-                        getReceiver(listener));
+                        getReceiver(listener, packageName));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1194,7 +1210,9 @@
     }
 
     public void requestLocationUpdatesPI(String provider, Criteria criteria,
-            long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
+            long minTime, float minDistance, boolean singleShot, PendingIntent intent,
+            String packageName) {
+        checkPackageName(Binder.getCallingUid(), packageName);
         validatePendingIntent(intent);
         if (criteria != null) {
             // FIXME - should we consider using multiple providers simultaneously
@@ -1208,7 +1226,7 @@
         try {
             synchronized (mLock) {
                 requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
-                        getReceiver(intent));
+                        getReceiver(intent, packageName));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1270,10 +1288,10 @@
         }
     }
 
-    public void removeUpdates(ILocationListener listener) {
+    public void removeUpdates(ILocationListener listener, String packageName) {
         try {
             synchronized (mLock) {
-                removeUpdatesLocked(getReceiver(listener));
+                removeUpdatesLocked(getReceiver(listener, packageName));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1284,10 +1302,10 @@
         }
     }
 
-    public void removeUpdatesPI(PendingIntent intent) {
+    public void removeUpdatesPI(PendingIntent intent, String packageName) {
         try {
             synchronized (mLock) {
-                removeUpdatesLocked(getReceiver(intent));
+                removeUpdatesLocked(getReceiver(intent, packageName));
             }
         } catch (SecurityException se) {
             throw se;
@@ -1446,15 +1464,17 @@
         final long mExpiration;
         final PendingIntent mIntent;
         final Location mLocation;
+        final String mPackageName;
 
         public ProximityAlert(int uid, double latitude, double longitude,
-            float radius, long expiration, PendingIntent intent) {
+            float radius, long expiration, PendingIntent intent, String packageName) {
             mUid = uid;
             mLatitude = latitude;
             mLongitude = longitude;
             mRadius = radius;
             mExpiration = expiration;
             mIntent = intent;
+            mPackageName = packageName;
 
             mLocation = new Location("");
             mLocation.setLatitude(latitude);
@@ -1522,6 +1542,10 @@
                 PendingIntent intent = alert.getIntent();
                 long expiration = alert.getExpiration();
 
+                if (inBlacklist(alert.mPackageName)) {
+                    continue;
+                }
+
                 if ((expiration == -1) || (now <= expiration)) {
                     boolean entered = mProximitiesEntered.contains(alert);
                     boolean inProximity =
@@ -1632,11 +1656,12 @@
     }
 
     public void addProximityAlert(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent) {
+        float radius, long expiration, PendingIntent intent, String packageName) {
         validatePendingIntent(intent);
         try {
             synchronized (mLock) {
-                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
+                addProximityAlertLocked(latitude, longitude, radius, expiration, intent,
+                        packageName);
             }
         } catch (SecurityException se) {
             throw se;
@@ -1648,7 +1673,7 @@
     }
 
     private void addProximityAlertLocked(double latitude, double longitude,
-        float radius, long expiration, PendingIntent intent) {
+        float radius, long expiration, PendingIntent intent, String packageName) {
         if (LOCAL_LOGV) {
             Slog.v(TAG, "addProximityAlert: latitude = " + latitude +
                     ", longitude = " + longitude +
@@ -1656,6 +1681,8 @@
                     ", intent = " + intent);
         }
 
+        checkPackageName(Binder.getCallingUid(), packageName);
+
         // Require ability to access all providers for now
         if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
             !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
@@ -1666,12 +1693,12 @@
             expiration += System.currentTimeMillis();
         }
         ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
-                latitude, longitude, radius, expiration, intent);
+                latitude, longitude, radius, expiration, intent, packageName);
         mProximityAlerts.put(intent, alert);
 
         if (mProximityReceiver == null) {
             mProximityListener = new ProximityListener();
-            mProximityReceiver = new Receiver(mProximityListener);
+            mProximityReceiver = new Receiver(mProximityListener, packageName);
 
             for (int i = mProviders.size() - 1; i >= 0; i--) {
                 LocationProviderInterface provider = mProviders.get(i);
@@ -1787,13 +1814,13 @@
         return isAllowedBySettingsLocked(provider);
     }
 
-    public Location getLastKnownLocation(String provider) {
+    public Location getLastKnownLocation(String provider, String packageName) {
         if (LOCAL_LOGV) {
             Slog.v(TAG, "getLastKnownLocation: " + provider);
         }
         try {
             synchronized (mLock) {
-                return _getLastKnownLocationLocked(provider);
+                return _getLastKnownLocationLocked(provider, packageName);
             }
         } catch (SecurityException se) {
             throw se;
@@ -1803,8 +1830,9 @@
         }
     }
 
-    private Location _getLastKnownLocationLocked(String provider) {
+    private Location _getLastKnownLocationLocked(String provider, String packageName) {
         checkPermissionsSafe(provider, null);
+        checkPackageName(Binder.getCallingUid(), packageName);
 
         LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
@@ -1815,6 +1843,10 @@
             return null;
         }
 
+        if (inBlacklist(packageName)) {
+            return null;
+        }
+
         return mLastKnownLocation.get(provider);
     }
 
@@ -1877,6 +1909,10 @@
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
 
+            if (inBlacklist(receiver.mPackageName)) {
+                continue;
+            }
+
             Location lastLoc = r.mLastFixBroadcast;
             if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
                 if (lastLoc == null) {
@@ -2315,6 +2351,113 @@
         }
     }
 
+    public class BlacklistObserver extends ContentObserver {
+        public BlacklistObserver(Handler handler) {
+            super(handler);
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            reloadBlacklist();
+        }
+    }
+
+    private void loadBlacklist() {
+        // Register for changes
+        BlacklistObserver observer = new BlacklistObserver(mLocationHandler);
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                BLACKLIST_CONFIG_NAME), false, observer);
+        mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
+                WHITELIST_CONFIG_NAME), false, observer);
+        reloadBlacklist();
+    }
+
+    private void reloadBlacklist() {
+        String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME);
+        String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME);
+        synchronized (mLock) {
+            mWhitelist = whitelist;
+            Slog.i(TAG, "whitelist: " + arrayToString(mWhitelist));
+            mBlacklist = blacklist;
+            Slog.i(TAG, "blacklist: " + arrayToString(mBlacklist));
+        }
+    }
+
+    private static String arrayToString(String[] array) {
+        StringBuilder s = new StringBuilder();
+        s.append('[');
+        boolean first = true;
+        for (String a : array) {
+            if (!first) s.append(',');
+            first = false;
+            s.append(a);
+        }
+        s.append(']');
+        return s.toString();
+    }
+
+    private String[] getStringArray(String key) {
+        String flatString = Settings.Secure.getString(mContext.getContentResolver(), key);
+        if (flatString == null) {
+            return new String[0];
+        }
+        String[] splitStrings = flatString.split(",");
+        ArrayList<String> result = new ArrayList<String>();
+        for (String pkg : splitStrings) {
+            pkg = pkg.trim();
+            if (pkg.isEmpty()) {
+                continue;
+            }
+            result.add(pkg);
+        }
+        return result.toArray(new String[result.size()]);
+    }
+
+    /**
+     * Return true if in blacklist, and not in whitelist.
+     */
+    private boolean inBlacklist(String packageName) {
+        synchronized (mLock) {
+            for (String black : mBlacklist) {
+                if (packageName.startsWith(black)) {
+                    if (inWhitelist(packageName)) {
+                        continue;
+                    } else {
+                        if (LOCAL_LOGV) Log.d(TAG, "dropping location (blacklisted): "
+                                + packageName + " matches " + black);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return true if any of packages are in whitelist
+     */
+    private boolean inWhitelist(String pkg) {
+        synchronized (mLock) {
+            for (String white : mWhitelist) {
+                if (pkg.startsWith(white)) return true;
+            }
+        }
+        return false;
+    }
+
+    private void checkPackageName(int uid, String packageName) {
+        if (packageName == null) {
+            throw new SecurityException("packageName cannot be null");
+        }
+        String[] packages = mPackageManager.getPackagesForUid(uid);
+        if (packages == null) {
+            throw new SecurityException("invalid UID " + uid);
+        }
+        for (String pkg : packages) {
+            if (packageName.equals(pkg)) return;
+        }
+        throw new SecurityException("invalid package name");
+    }
+
     private void log(String log) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Slog.d(TAG, log);
@@ -2346,6 +2489,8 @@
                     j.getValue().dump(pw, "        ");
                 }
             }
+            pw.println("  Package blacklist:" + arrayToString(mBlacklist));
+            pw.println("  Package whitelist:" + arrayToString(mWhitelist));
             pw.println("  Records by Provider:");
             for (Map.Entry<String, ArrayList<UpdateRecord>> i
                     : mRecordsByProvider.entrySet()) {