Merge "DO NOT MERGE Added report button to UI and database." into lmp-dev
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index 609f2a9..22fcca0 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -73,8 +73,25 @@
             android:textSize="@dimen/call_log_list_item_actions_text_size"
             android:textStyle="bold"
             android:nextFocusLeft="@+id/voicemail_action"
-            android:nextFocusRight="@+id/primary_action_view"
+            android:nextFocusRight="@+id/report_action"
             android:focusable="true"
             android:singleLine="true"/>
+        <TextView
+            android:id="@+id/report_action"
+            android:background="@drawable/action_button_background"
+            android:gravity="center"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingStart="@dimen/call_log_action_horizontal_padding"
+            android:paddingEnd="@dimen/call_log_action_horizontal_padding"
+            android:text="@string/call_log_action_report"
+            android:textColor="?attr/call_log_secondary_text_color"
+            android:textSize="@dimen/call_log_list_item_actions_text_size"
+            android:textStyle="bold"
+            android:nextFocusLeft="@+id/details_action"
+            android:nextFocusRight="@+id/primary_action_view"
+            android:focusable="true"
+            android:singleLine="true"
+            android:visibility="gone"/>
     </LinearLayout>
 </FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e7d93e..e51aff7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -685,6 +685,15 @@
          [CHAR LIMIT=NONE] -->
     <string name="toast_entry_removed">Call log entry deleted.</string>
 
+    <!-- Toast message which appears when a call log contact is reported.
+         [CHAR LIMIT=NONE] -->
+    <string name="toast_caller_id_reported">Contact reported.</string>
+
+    <!-- Button text for the "report" button displayed underneath an entry in the call log.
+         Tapping causes the call log entry to be reported to Google as a bad id.
+         [CHAR LIMIT=30] -->
+    <string name="call_log_action_report">REPORT</string>
+
     <!-- String used as a header in the call log above calls which occurred today.
          [CHAR LIMIT=65] -->
     <string name="call_log_header_today">Today</string>
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 5bebd40..f4b9f3a 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -37,6 +37,7 @@
 import android.view.ViewTreeObserver;
 import android.widget.ImageView;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.android.common.widget.GroupingListAdapter;
 import com.android.contacts.common.ContactPhotoManager;
@@ -131,6 +132,7 @@
     protected final Context mContext;
     private final ContactInfoHelper mContactInfoHelper;
     private final CallFetcher mCallFetcher;
+    private final Toast mReportedToast;
     private ViewTreeObserver mViewTreeObserver = null;
 
     /**
@@ -351,6 +353,9 @@
         mIsCallLog = isCallLog;
         mCallItemExpandedListener = callItemExpandedListener;
 
+        mReportedToast = Toast.makeText(mContext, R.string.toast_caller_id_reported,
+                Toast.LENGTH_SHORT);
+
         mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
         mRequests = new LinkedList<ContactInfoRequest>();
 
@@ -751,6 +756,9 @@
 
         final PhoneCallDetails details;
 
+        views.reported = info.isBadData;
+        views.isExternal = mContactInfoHelper.isExternal(info.sourceType);
+
         if (TextUtils.isEmpty(name)) {
             details = new PhoneCallDetails(number, numberPresentation,
                     formattedNumber, countryIso, geocode, callTypes, date,
@@ -908,7 +916,7 @@
      *
      * @param callLogItem The call log list item view.
      */
-    private void inflateActionViewStub(View callLogItem) {
+    private void inflateActionViewStub(final View callLogItem) {
         final CallLogListItemViews views = (CallLogListItemViews)callLogItem.getTag();
 
         ViewStub stub = (ViewStub)callLogItem.findViewById(R.id.call_log_entry_actions_stub);
@@ -930,6 +938,19 @@
             views.detailsButtonView = (TextView)views.actionsView.findViewById(R.id.details_action);
         }
 
+        if (views.reportButtonView == null) {
+            views.reportButtonView = (TextView)views.actionsView.findViewById(R.id.report_action);
+            views.reportButtonView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mReportedToast.show();
+                    ((CallLogListItemViews) callLogItem.getTag()).reported = true;
+                    v.setVisibility(View.GONE);
+                    // TODO: Set the entry as reported in the database.
+                }
+            });
+        }
+
         bindActionButtons(views);
     }
 
@@ -970,7 +991,9 @@
                     IntentProvider.getCallDetailIntentProvider(
                             views.rowId, views.callIds, null)
             );
-
+            if (views.isExternal && !views.reported) {
+                views.reportButtonView.setVisibility(View.VISIBLE);
+            }
         }
 
         mCallLogViewsHelper.setActionContentDescriptions(views);
diff --git a/src/com/android/dialer/calllog/CallLogListItemViews.java b/src/com/android/dialer/calllog/CallLogListItemViews.java
index 8048d83..3efa5cb 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViews.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViews.java
@@ -48,6 +48,8 @@
     public TextView voicemailButtonView;
     /** The "details" action button - assigned only when the action section is expanded. */
     public TextView detailsButtonView;
+    /** The "report" action button. */
+    public TextView reportButtonView;
 
     /**
      * The row Id for the first call associated with the call log entry.  Used as a key for the
@@ -98,6 +100,16 @@
      */
     public CharSequence nameOrNumber;
 
+    /**
+     * Whether or not the item has been reported by user as incorrect.
+     */
+    public boolean reported;
+
+    /**
+     * Whether or not the contact info came from a source other than the android contacts provider.
+     */
+    public boolean isExternal;
+
     private CallLogListItemViews(QuickContactBadge quickContactView, View primaryActionView,
             PhoneCallDetailsViews phoneCallDetailsViews, View callLogEntryView,
             TextView dayGroupHeader) {
@@ -128,6 +140,7 @@
         views.callBackButtonView = new TextView(context);
         views.voicemailButtonView = new TextView(context);
         views.detailsButtonView = new TextView(context);
+        views.reportButtonView = new TextView(context);
         views.actionsView = new View(context);
         return views;
     }
diff --git a/src/com/android/dialer/calllog/ContactInfo.java b/src/com/android/dialer/calllog/ContactInfo.java
index 41afa5a..cf29c5c 100644
--- a/src/com/android/dialer/calllog/ContactInfo.java
+++ b/src/com/android/dialer/calllog/ContactInfo.java
@@ -38,6 +38,7 @@
     public long photoId;
     /** The high-res photo for the contact, if available. */
     public Uri photoUri;
+    public boolean isBadData;
 
     public static ContactInfo EMPTY = new ContactInfo();
 
diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java
index 1bebfc4..f09c365 100644
--- a/src/com/android/dialer/calllog/ContactInfoHelper.java
+++ b/src/com/android/dialer/calllog/ContactInfoHelper.java
@@ -288,4 +288,16 @@
         return mCachedNumberLookupService != null
                 && mCachedNumberLookupService.isBusiness(sourceType);
     }
+
+    /**
+     * Given a contact's sourceType, return true if the contact came from an
+     * external source.
+     *
+     * @param sourceType sourceType of the contact. This is usually populated by
+     *        {@link #mCachedNumberLookupService}.
+     */
+    public boolean isExternal(int sourceType) {
+        return mCachedNumberLookupService != null
+                && mCachedNumberLookupService.isExternal(sourceType);
+    }
 }
diff --git a/src/com/android/dialer/service/CachedNumberLookupService.java b/src/com/android/dialer/service/CachedNumberLookupService.java
index 73fd895..2fec45c 100644
--- a/src/com/android/dialer/service/CachedNumberLookupService.java
+++ b/src/com/android/dialer/service/CachedNumberLookupService.java
@@ -35,6 +35,8 @@
 
     public boolean isBusiness(int sourceType);
 
+    public boolean isExternal(int sourceType);
+
     public boolean addPhoto(Context context, String number, byte[] photo);
 
     /**