1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.calldetails; 18 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.DialogFragment; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.os.Bundle; 25 import android.support.annotation.Nullable; 26 import android.support.v4.util.Pair; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.widget.TextView; 30 import android.widget.Toast; 31 import com.android.dialer.common.LogUtil; 32 import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener; 33 import com.android.dialer.common.concurrent.DialerExecutor.Worker; 34 import com.android.dialer.common.concurrent.DialerExecutorComponent; 35 import com.android.dialer.logging.DialerImpression; 36 import com.android.dialer.logging.Logger; 37 import com.android.dialer.phonenumbercache.CachedNumberLookupService; 38 import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo; 39 import com.android.dialer.phonenumbercache.PhoneNumberCache; 40 import com.android.dialer.theme.base.ThemeComponent; 41 42 /** Dialog for reporting an inaccurate caller id information. */ 43 public class ReportDialogFragment extends DialogFragment { 44 45 private static final String KEY_NUMBER = "number"; 46 private TextView name; 47 private TextView numberView; 48 49 private CachedNumberLookupService cachedNumberLookupService; 50 private CachedNumberLookupService.CachedContactInfo info; 51 private String number; 52 newInstance(String number)53 public static ReportDialogFragment newInstance(String number) { 54 ReportDialogFragment fragment = new ReportDialogFragment(); 55 Bundle bundle = new Bundle(); 56 bundle.putString(KEY_NUMBER, number); 57 fragment.setArguments(bundle); 58 return fragment; 59 } 60 61 @Override onCreate(@ullable Bundle bundle)62 public void onCreate(@Nullable Bundle bundle) { 63 super.onCreate(bundle); 64 setRetainInstance(true); 65 number = getArguments().getString(KEY_NUMBER); 66 cachedNumberLookupService = PhoneNumberCache.get(getContext()).getCachedNumberLookupService(); 67 } 68 69 @Override onCreateDialog(Bundle savedInstanceState)70 public Dialog onCreateDialog(Bundle savedInstanceState) { 71 LayoutInflater inflater = getActivity().getLayoutInflater(); 72 View view = inflater.inflate(R.layout.caller_id_report_dialog, null, false); 73 name = view.findViewById(R.id.name); 74 numberView = view.findViewById(R.id.number); 75 76 lookupContactInfo(number); 77 78 AlertDialog reportDialog = 79 new AlertDialog.Builder(getActivity()) 80 .setTitle(R.string.report_caller_id_dialog_title) 81 .setPositiveButton(android.R.string.ok, (dialog, which) -> positiveClick(dialog)) 82 .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss()) 83 .setView(view) 84 .create(); 85 86 reportDialog.setOnShowListener(dialog -> onShow(getContext(), reportDialog)); 87 return reportDialog; 88 } 89 positiveClick(DialogInterface dialog)90 private void positiveClick(DialogInterface dialog) { 91 startReportCallerIdWorker(); 92 dialog.dismiss(); 93 } 94 onShow(Context context, AlertDialog dialog)95 private static void onShow(Context context, AlertDialog dialog) { 96 int buttonTextColor = ThemeComponent.get(context).theme().getColorPrimary(); 97 dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(buttonTextColor); 98 dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(buttonTextColor); 99 } 100 lookupContactInfo(String number)101 private void lookupContactInfo(String number) { 102 Worker<String, CachedContactInfo> worker = 103 number1 -> cachedNumberLookupService.lookupCachedContactFromNumber(getContext(), number1); 104 SuccessListener<CachedContactInfo> successListener = this::setCachedContactInfo; 105 DialerExecutorComponent.get(getContext()) 106 .dialerExecutorFactory() 107 .createUiTaskBuilder(getFragmentManager(), "lookup_contact_info", worker) 108 .onSuccess(successListener) 109 .build() 110 .executeParallel(number); 111 } 112 setCachedContactInfo(CachedContactInfo info)113 private void setCachedContactInfo(CachedContactInfo info) { 114 this.info = info; 115 if (info != null) { 116 name.setText(info.getContactInfo().name); 117 numberView.setText(info.getContactInfo().number); 118 } else { 119 numberView.setText(number); 120 name.setVisibility(View.GONE); 121 } 122 } 123 startReportCallerIdWorker()124 private void startReportCallerIdWorker() { 125 Worker<Context, Pair<Context, Boolean>> worker = this::reportCallerId; 126 SuccessListener<Pair<Context, Boolean>> successListener = this::onReportCallerId; 127 DialerExecutorComponent.get(getContext()) 128 .dialerExecutorFactory() 129 .createUiTaskBuilder(getFragmentManager(), "report_caller_id", worker) 130 .onSuccess(successListener) 131 .build() 132 .executeParallel(getActivity()); 133 } 134 reportCallerId(Context context)135 private Pair<Context, Boolean> reportCallerId(Context context) { 136 if (cachedNumberLookupService.reportAsInvalid(context, info)) { 137 info.getContactInfo().isBadData = true; 138 cachedNumberLookupService.addContact(context, info); 139 LogUtil.d("ReportUploadTask.doInBackground", "Contact reported."); 140 return new Pair<>(context, true); 141 } else { 142 return new Pair<>(context, false); 143 } 144 } 145 onReportCallerId(Pair<Context, Boolean> output)146 private void onReportCallerId(Pair<Context, Boolean> output) { 147 Context context = output.first; 148 boolean wasReport = output.second; 149 if (wasReport) { 150 Logger.get(context).logImpression(DialerImpression.Type.CALLER_ID_REPORTED); 151 Toast.makeText(context, R.string.report_caller_id_toast, Toast.LENGTH_SHORT).show(); 152 } else { 153 Logger.get(context).logImpression(DialerImpression.Type.CALLER_ID_REPORT_FAILED); 154 Toast.makeText(context, R.string.report_caller_id_failed, Toast.LENGTH_SHORT).show(); 155 } 156 } 157 158 @Override onDestroyView()159 public void onDestroyView() { 160 if (getDialog() != null && getRetainInstance()) { 161 // Prevent dialog from dismissing on rotate. 162 getDialog().setDismissMessage(null); 163 } 164 super.onDestroyView(); 165 } 166 } 167