Add hamburger menu to PeopleActivity

1. This CL moves "settings" and "help & feedback" to hamburger menu.
2. Changes in people_activity.xml may be hard to read. We just wrap the
   existing content of people_activity.xml with DrawerLayout and add a
   NavigationView below it: https://paste.googleplex.com/6376771465248768
3. Screenshot https://goto.google.com/contacts-hamburger

Bug 27687799

Change-Id: Ia8ce3746cee9ad63689157dbe0b1ea81200bedf6
diff --git a/Android.mk b/Android.mk
index ad13292..fc29430 100644
--- a/Android.mk
+++ b/Android.mk
@@ -20,24 +20,30 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs))
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs)) \
+    $(support_library_root_dir)/design/res \
     $(support_library_root_dir)/v7/appcompat/res \
-    $(support_library_root_dir)/v7/cardview/res
+    $(support_library_root_dir)/v7/cardview/res \
+    $(support_library_root_dir)/v7/recyclerview/res
 LOCAL_ASSET_DIR := $(addprefix $(LOCAL_PATH)/, $(asset_dirs))
 
 LOCAL_AAPT_FLAGS := \
     --auto-add-overlay \
     --extra-packages com.android.contacts.common \
     --extra-packages com.android.phone.common \
+    --extra-packages android.support.design \
     --extra-packages android.support.v7.appcompat \
-    --extra-packages android.support.v7.cardview
+    --extra-packages android.support.v7.cardview \
+    --extra-packages android.support.v7.recyclerview
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     com.android.vcard \
     android-common \
     guava \
+    android-support-design \
     android-support-v13 \
     android-support-v7-appcompat \
     android-support-v7-cardview \
+    android-support-v7-recyclerview \
     android-support-v7-palette \
     android-support-v4 \
     libphonenumber
diff --git a/res/drawable/ic_menu_hamburger.xml b/res/drawable/ic_menu_hamburger.xml
new file mode 100644
index 0000000..dfe4269
--- /dev/null
+++ b/res/drawable/ic_menu_hamburger.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_menu_help.xml b/res/drawable/ic_menu_help.xml
new file mode 100644
index 0000000..bba36a2
--- /dev/null
+++ b/res/drawable/ic_menu_help.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/>
+</vector>
diff --git a/res/drawable/ic_menu_settings.xml b/res/drawable/ic_menu_settings.xml
new file mode 100644
index 0000000..e9a2078
--- /dev/null
+++ b/res/drawable/ic_menu_settings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportHeight="24.0"
+        android:viewportWidth="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/>
+</vector>
diff --git a/res/drawable/side_nav_bar.xml b/res/drawable/side_nav_bar.xml
new file mode 100644
index 0000000..b67bfb5
--- /dev/null
+++ b/res/drawable/side_nav_bar.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <gradient
+        android:angle="135"
+        android:endColor="@color/primary_color_dark"
+        android:startColor="@color/primary_color"
+        android:type="linear"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/nav_header_main.xml b/res/layout/nav_header_main.xml
new file mode 100644
index 0000000..cd6d559
--- /dev/null
+++ b/res/layout/nav_header_main.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (C) 2016 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/nav_header_height"
+    android:background="@drawable/side_nav_bar"
+    android:gravity="bottom"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/nav_activity_vertical_margin"
+    android:paddingLeft="@dimen/nav_activity_horizontal_margin"
+    android:paddingRight="@dimen/nav_activity_horizontal_margin"
+    android:paddingTop="@dimen/nav_activity_vertical_margin"
+    android:theme="@style/ThemeOverlay.AppCompat.Dark">
+</LinearLayout>
diff --git a/res/layout/people_activity.xml b/res/layout/people_activity.xml
index ce995cb..8282e91 100644
--- a/res/layout/people_activity.xml
+++ b/res/layout/people_activity.xml
@@ -14,40 +14,61 @@
      limitations under the License.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/list_container"
+<android.support.v4.widget.DrawerLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true"
+    tools:openDrawer="start">
 
-    <include
-        layout="@layout/people_activity_toolbar"
-        android:id="@+id/toolbar_parent" />
-
-    <!--
-        ViewPager for swiping between tabs.  We put StrequentContactListFragment,
-        DefaultContactBrowseListFragment and GroupBrowseListFragment at runtime.
-
-        (Adding them directly as the children of this view is not recommended.  ViewPager should
-        be treated like a ListView, which doesn't expect children to be added from the layout.)
-    -->
-    <android.support.v4.view.ViewPager
-        android:id="@+id/tab_pager"
-        android:layout_height="match_parent"
+    <RelativeLayout
+        android:id="@+id/list_container"
         android:layout_width="match_parent"
-        android:layout_below="@id/toolbar_parent"
-        />
+        android:layout_height="match_parent">
 
-    <FrameLayout
-        android:id="@+id/contacts_unavailable_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_below="@id/toolbar_parent"
-        android:visibility="gone">
-        <FrameLayout
-            android:id="@+id/contacts_unavailable_container"
+        <include
+            layout="@layout/people_activity_toolbar"
+            android:id="@+id/toolbar_parent" />
+
+        <!--
+            ViewPager for swiping between tabs.  We put StrequentContactListFragment,
+            DefaultContactBrowseListFragment and GroupBrowseListFragment at runtime.
+
+            (Adding them directly as the children of this view is not recommended.  ViewPager should
+            be treated like a ListView, which doesn't expect children to be added from the layout.)
+        -->
+        <android.support.v4.view.ViewPager
+            android:id="@+id/tab_pager"
             android:layout_height="match_parent"
-            android:layout_width="match_parent" />
-    </FrameLayout>
+            android:layout_width="match_parent"
+            android:layout_below="@id/toolbar_parent"
+            />
 
-    <include layout="@layout/floating_action_button" />
-</RelativeLayout>
+        <FrameLayout
+            android:id="@+id/contacts_unavailable_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_below="@id/toolbar_parent"
+            android:visibility="gone">
+            <FrameLayout
+                android:id="@+id/contacts_unavailable_container"
+                android:layout_height="match_parent"
+                android:layout_width="match_parent" />
+        </FrameLayout>
+
+        <include layout="@layout/floating_action_button" />
+    </RelativeLayout>
+
+    <android.support.design.widget.NavigationView
+        android:id="@+id/nav_view"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="start"
+        android:fitsSystemWindows="true"
+        app:headerLayout="@layout/nav_header_main"
+        app:menu="@menu/activity_main_drawer"/>
+
+</android.support.v4.widget.DrawerLayout>
\ No newline at end of file
diff --git a/res/menu/activity_main_drawer.xml b/res/menu/activity_main_drawer.xml
new file mode 100644
index 0000000..0a0eef2
--- /dev/null
+++ b/res/menu/activity_main_drawer.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (C) 2016 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.
+  -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <group android:id="@+id/misc">
+        <item
+            android:id="@+id/nav_settings"
+            android:icon="@drawable/ic_menu_settings"
+            android:title="@string/menu_settings"/>
+    </group>
+
+</menu>
diff --git a/res/menu/menu_help.xml b/res/menu/menu_help.xml
new file mode 100644
index 0000000..3b5d3df
--- /dev/null
+++ b/res/menu/menu_help.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (C) 2016 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.
+  -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/nav_help"/>
+</menu>
\ No newline at end of file
diff --git a/res/menu/people_options.xml b/res/menu/people_options.xml
index 032bea6..4c8b21d 100644
--- a/res/menu/people_options.xml
+++ b/res/menu/people_options.xml
@@ -42,14 +42,6 @@
         android:title="@string/menu_accounts" />
 
     <item
-        android:id="@+id/menu_settings"
-        android:title="@string/menu_settings" />
-
-    <item
-        android:id="@+id/menu_help"
-        android:title="@string/menu_help" />
-
-    <item
         android:id="@+id/export_database"
         android:title="@string/menu_export_database"
         android:visible="false"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e18156f..c429ec9 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -291,4 +291,11 @@
     <!-- Top margin for "Saving to" account header text field. -->
     <dimen name="compact_editor_account_header_top_margin">3dp</dimen>
 
+    <!-- Navigation drawer header height, per the Android Design guidelines. -->
+    <dimen name="nav_header_height">160dp</dimen>
+
+    <!-- Navigation drawer margins, per the Android Design guidelines. -->
+    <dimen name="nav_activity_horizontal_margin">16dp</dimen>
+    <dimen name="nav_activity_vertical_margin">16dp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f3a9d2c..3bf1737 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -919,4 +919,10 @@
 
     <!-- The menu item to open the link/merge duplicates activity. [CHAR LIMIT=80]-->
     <string name="menu_duplicates">Find duplicates</string>
+
+    <!-- Open drawer content descriptions [CHAR LIMIT=40] -->
+    <string name="navigation_drawer_open">Open navigation drawer</string>
+
+    <!-- Close drawer content descriptions [CHAR LIMIT=40] -->
+    <string name="navigation_drawer_close">Close navigation drawer</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 5309a55..482fc28 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -130,6 +130,7 @@
         <!-- Style for the overflow button in the actionbar. -->
         <item name="android:actionOverflowButtonStyle">@style/ContactsActionBarOverflowQP</item>
         <item name="actionOverflowButtonStyle">@style/ContactsActionBarOverflowQP</item>
+        <item name="toolbarNavigationButtonStyle">@style/ContactToolbarNavigationButtonStyle</item>
         <item name="android:actionModeCloseDrawable">@drawable/ic_close_lt</item>
         <item name="android:fastScrollThumbDrawable">@drawable/fastscroll_thumb</item>
         <item name="android:fastScrollTrackDrawable">@null</item>
@@ -271,6 +272,11 @@
         <item name="android:tint">@color/action_bar_button_text_color</item>
     </style>
 
+    <!-- Toolbar navigation button. -->
+    <style name="ContactToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
+        <item name="android:tint">@color/action_bar_button_text_color</item>
+    </style>
+
     <style name="ContactsActionBarDropDownStyle" parent="@android:style/Widget.Holo.Light.Spinner">
         <item name="android:background">@drawable/ab_dropdown_navigation_item_background</item>
     </style>
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index ad70d92..46bb9c9 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -366,6 +366,9 @@
             newFlags |= ActionBar.DISPLAY_SHOW_TITLE;
             mToolbar.setContentInsetsRelative(mMaxToolbarContentInsetStart,
                     mToolbar.getContentInsetEnd());
+            mToolbar.setNavigationIcon(R.drawable.ic_menu_hamburger);
+        } else {
+            mToolbar.setNavigationIcon(null);
         }
 
         if (mSelectionMode) {
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index a26148a..66a29de 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -34,9 +34,13 @@
 import android.provider.ContactsContract.ProviderStatus;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.Settings;
+import android.support.design.widget.NavigationView;
 import android.support.v13.app.FragmentPagerAdapter;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewPager;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.widget.Toolbar;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
@@ -112,7 +116,8 @@
         ContactListFilterController.ContactListFilterListener,
         ProviderStatusListener,
         MultiContactDeleteListener,
-        JoinContactsListener {
+        JoinContactsListener,
+        NavigationView.OnNavigationItemSelectedListener {
 
     private static final String TAG = "PeopleActivity";
 
@@ -329,6 +334,22 @@
         }
         mViewPagerTabs.setViewPager(mTabPager);
 
+        final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
+                R.string.navigation_drawer_open, R.string.navigation_drawer_close);
+        drawer.setDrawerListener(toggle);
+        toggle.syncState();
+
+        final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+        navigationView.setNavigationItemSelectedListener(this);
+
+        final Menu menu = navigationView.getMenu();
+        if (HelpUtils.isHelpAndFeedbackAvailable()) {
+            final MenuItem menuItem = menu.add(/* groupId */ R.id.misc, /* itemId */ R.id.nav_help,
+                    /* order */ Menu.NONE, /* titleRes */ R.string.menu_help);
+            menuItem.setIcon(R.drawable.ic_menu_help);
+        }
+
         final String FAVORITE_TAG = "tab-pager-favorite";
         final String ALL_TAG = "tab-pager-all";
 
@@ -1076,14 +1097,12 @@
         // Get references to individual menu items in the menu
         final MenuItem contactsFilterMenu = menu.findItem(R.id.menu_contacts_filter);
         final MenuItem clearFrequentsMenu = menu.findItem(R.id.menu_clear_frequents);
-        final MenuItem helpMenu = menu.findItem(R.id.menu_help);
 
         final boolean isSearchOrSelectionMode = mActionBarAdapter.isSearchMode()
                 || mActionBarAdapter.isSelectionMode();
         if (isSearchOrSelectionMode) {
             contactsFilterMenu.setVisible(false);
             clearFrequentsMenu.setVisible(false);
-            helpMenu.setVisible(false);
         } else {
             switch (getTabPositionForTextDirection(mActionBarAdapter.getCurrentTab())) {
                 case TabState.FAVORITES:
@@ -1095,7 +1114,6 @@
                     clearFrequentsMenu.setVisible(false);
                     break;
             }
-            helpMenu.setVisible(HelpUtils.isHelpAndFeedbackAvailable());
         }
         final boolean showMiscOptions = !isSearchOrSelectionMode;
         final boolean showBlockedNumbers = PhoneCapabilityTester.isPhone(this)
@@ -1105,8 +1123,6 @@
         makeMenuItemVisible(menu, R.id.menu_import_export, showMiscOptions);
         makeMenuItemVisible(menu, R.id.menu_accounts, showMiscOptions);
         makeMenuItemVisible(menu, R.id.menu_blocked_numbers, showMiscOptions && showBlockedNumbers);
-        makeMenuItemVisible(menu, R.id.menu_settings,
-                showMiscOptions && !ContactsPreferenceActivity.isEmpty(this));
         makeMenuItemVisible(menu, R.id.menu_duplicates,
                 showMiscOptions && ObjectFactory.getDuplicatesActivityIntent(this) != null);
 
@@ -1170,10 +1186,6 @@
                 }
                 return true;
             }
-            case R.id.menu_settings: {
-                startActivity(new Intent(this, ContactsPreferenceActivity.class));
-                return true;
-            }
             case R.id.menu_contacts_filter: {
                 AccountFilterUtil.startAccountFilterActivityForResult(
                         this, SUBACTIVITY_ACCOUNT_FILTER,
@@ -1201,9 +1213,6 @@
                 ClearFrequentsDialog.show(getFragmentManager());
                 return true;
             }
-            case R.id.menu_help:
-                HelpUtils.launchHelpAndFeedbackForMainScreen(this);
-                return true;
             case R.id.menu_accounts: {
                 final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
                 intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {
@@ -1236,6 +1245,22 @@
         return false;
     }
 
+    @SuppressWarnings("StatementWithEmptyBody")
+    @Override
+    public boolean onNavigationItemSelected(MenuItem item) {
+        final int id = item.getItemId();
+
+        if (id == R.id.nav_settings) {
+            startActivity(new Intent(this, ContactsPreferenceActivity.class));
+        } else if (id == R.id.nav_help) {
+            HelpUtils.launchHelpAndFeedbackForMainScreen(this);
+        }
+
+        final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        drawer.closeDrawer(GravityCompat.START);
+        return true;
+    }
+
     private void showImportExportDialogFragment(){
         final boolean isOnFavoriteTab = mTabPagerAdapter.mCurrentPrimaryItem == mFavoritesFragment;
         if (isOnFavoriteTab) {
@@ -1365,7 +1390,10 @@
             return;
         }
 
-        if (mActionBarAdapter.isSelectionMode()) {
+        final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        if (drawer.isDrawerOpen(GravityCompat.START)) {
+            drawer.closeDrawer(GravityCompat.START);
+        } else if (mActionBarAdapter.isSelectionMode()) {
             mActionBarAdapter.setSelectionMode(false);
             mAllFragment.displayCheckBoxes(false);
         } else if (mActionBarAdapter.isSearchMode()) {