diff options
author | Kamaljeet Maini <kmaini@cyngn.com> | 2016-02-06 12:16:14 -0800 |
---|---|---|
committer | Stephen Bird <sbird@cyngn.com> | 2016-04-08 10:18:47 -0700 |
commit | 5c56a65a536c2c39110953592df992a2b12acf60 (patch) | |
tree | 78cfdc03776cf5268193ffbf14f109aeded06da3 /src | |
parent | acb0f2ed678dd2bdf3eaf7a857f0b27cd360670c (diff) | |
download | android_packages_apps_Dialer-5c56a65a536c2c39110953592df992a2b12acf60.tar.gz android_packages_apps_Dialer-5c56a65a536c2c39110953592df992a2b12acf60.tar.bz2 android_packages_apps_Dialer-5c56a65a536c2c39110953592df992a2b12acf60.zip |
Add CallerInfoProvider options in Settings
Issue-Id: DIALER-706
Change-Id: I4dee753f25b7a48baef64586bb565eed297014df
Diffstat (limited to 'src')
4 files changed, 450 insertions, 8 deletions
diff --git a/src/com/android/dialer/DialerApplication.java b/src/com/android/dialer/DialerApplication.java index 2173d7a57..9db00771a 100644 --- a/src/com/android/dialer/DialerApplication.java +++ b/src/com/android/dialer/DialerApplication.java @@ -22,6 +22,7 @@ import android.os.Trace; import com.android.contacts.common.extensions.ExtensionsFactory; import com.android.contacts.commonbind.analytics.AnalyticsUtil; import com.android.phone.common.incall.CallMethodHelper; +import com.android.dialer.util.MetricsHelper; public class DialerApplication extends Application { @@ -34,14 +35,18 @@ public class DialerApplication extends Application { public void onCreate() { Trace.beginSection(TAG + " onCreate"); super.onCreate(); + Trace.beginSection(TAG + " ExtensionsFactory initialization"); ExtensionsFactory.init(getApplicationContext()); Trace.endSection(); + Trace.beginSection(TAG + " Analytics initialization"); AnalyticsUtil.initialize(this); Trace.endSection(); - Trace.endSection(); + CallMethodHelper.init(this); DeepLinkIntegrationManager.getInstance().setUp(this); + MetricsHelper.init(this); + Trace.endSection(); } } diff --git a/src/com/android/dialer/callerinfo/CallerInfoProviderPicker.java b/src/com/android/dialer/callerinfo/CallerInfoProviderPicker.java new file mode 100644 index 000000000..423e0d1cd --- /dev/null +++ b/src/com/android/dialer/callerinfo/CallerInfoProviderPicker.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2013-2016 The CyanogenMod 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. + */ + +package com.android.dialer.callerinfo; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.os.Bundle; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import com.android.dialer.R; +import com.android.dialer.util.MetricsHelper; +import com.android.phone.common.ambient.AmbientConnection; +import com.cyanogen.ambient.callerinfo.util.CallerInfoHelper; +import com.cyanogen.ambient.callerinfo.util.ProviderInfo; +import com.cyanogen.ambient.callerinfo.CallerInfoServices; +import com.cyanogen.ambient.callerinfo.results.IsAuthenticatedResult; +import com.cyanogen.ambient.common.api.PendingResult; +import com.cyanogen.ambient.common.api.Result; +import com.cyanogen.ambient.common.api.ResultCallback; + +public class CallerInfoProviderPicker extends Activity { + + private static final String TAG = "CallerInfoProviderPicker"; + + public static final String METRICS_REASON_EXTRA = "reason_extra"; + public static final int REASON_FIRST_LAUNCH_DIALER = 0; + public static final int REASON_INCOMING_CALL = 1; + public static final int REASON_INCOMING_CALL_FINAL_PROMPT = 2; + public static final int REASON_DIALER_SETTINGS = 3; + + private AlertDialog mDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Resources res = getResources(); + final CallerInfoHelper.ResolvedProvider[] providers = + CallerInfoHelper.getInstalledProviders(this); + if (providers.length == 0) { + finish(); + return; + } + + View view = View.inflate(this, R.layout.callerinfo_provider_picker, null); + ImageView logo = (ImageView) view.findViewById(R.id.logo); + TextView description = (TextView) view.findViewById(R.id.description); + TextView disclaimer = (TextView) view.findViewById(R.id.disclaimer); + + // Assume only one provider + ProviderInfo info = CallerInfoHelper.getProviderInfo(this, providers[0].getComponent()); + if (info != null) { + if (info.hasProperty(ProviderInfo.PROPERTY_NEEDS_CONTACTS)) { + String text = res.getString(R.string.callerinfo_provider_auth_access, info.getTitle()); + if (info.getPrivacyPolicyUrl() != null) { + String learnMore = " <a href=\"%s\">%s</a>"; + text += String.format(learnMore, info.getPrivacyPolicyUrl(), + res.getString(R.string.callerinfo_provider_auth_learn_more)); + } + disclaimer.setMovementMethod(LinkMovementMethod.getInstance()); + disclaimer.setText(Html.fromHtml(text)); + } else { + disclaimer.setVisibility(View.GONE); + } + + logo.setImageDrawable(info.getBrandLogo()); + + int resId = info.hasProperty(ProviderInfo.PROPERTY_SUPPORTS_SPAM) ? + R.string.callerinfo_provider_auth_desc : R.string.callerinfo_provider_auth_desc_no_spam; + description.setText(res.getString(resId, info.getTitle())); + } + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setView(view); + builder.setPositiveButton(res.getString(R.string.callerinfo_provider_auth_yes), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + sendMetrics(true, providers[0].getPackageName()); + + CallerInfoHelper.setActiveProvider(CallerInfoProviderPicker.this, + providers[0].getComponent()); + PendingResult<IsAuthenticatedResult> result = + CallerInfoServices.CallerInfoApi.isAuthenticated( + AmbientConnection.CLIENT.get(getApplicationContext())); + result.setResultCallback(new ResultCallback<IsAuthenticatedResult>() { + @Override + public void onResult(IsAuthenticatedResult response) { + Log.d(TAG, "isAuthenticated = " + response.getIsAuthenticated()); + if (!response.getIsAuthenticated()) { + PendingResult<Result> result = + CallerInfoServices.CallerInfoApi.setupAuthentication + (AmbientConnection.CLIENT.get(getApplicationContext())); + } + finish(); + } + }); + } + }).setNegativeButton(res.getString(R.string.callerinfo_provider_auth_no), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + sendMetrics(false, providers[0].getPackageName()); + finish(); + } + }).setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + finish(); + } + }); + mDialog = builder.create(); + mDialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + int buttonColor = res.getColor(R.color.callerinfo_provider_picker_negative_color); + mDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(buttonColor); + } + }); + mDialog.show(); + } + + @Override + public void onStop() { + super.onStop(); + } + + void sendMetrics(boolean onAccept, String providerPackageName) { + if (!getIntent().hasExtra(METRICS_REASON_EXTRA)) { + return; + } + int reason = getIntent().getIntExtra(METRICS_REASON_EXTRA, -1); + MetricsHelper.Field field = new MetricsHelper.Field( + MetricsHelper.Fields.PROVIDER_PACKAGE_NAME, providerPackageName); + MetricsHelper.Actions action = onAccept ? + MetricsHelper.Actions.OPTED_IN : MetricsHelper.Actions.OPTED_OUT; + switch (reason) { + case REASON_FIRST_LAUNCH_DIALER: + MetricsHelper.sendEvent(MetricsHelper.Categories.PROVIDER_STATE_CHANGES, + action, MetricsHelper.State.FIRST_LAUNCH_DIALER, field); + break; + case REASON_INCOMING_CALL_FINAL_PROMPT: + MetricsHelper.sendEvent(MetricsHelper.Categories.PROVIDER_STATE_CHANGES, + action, MetricsHelper.State.AFTER_FINAL_PROMPT, field); + break; + case REASON_INCOMING_CALL: + MetricsHelper.sendEvent(MetricsHelper.Categories.PROVIDER_STATE_CHANGES, + action, MetricsHelper.State.AFTER_CALL_ENDED, field); + break; + case REASON_DIALER_SETTINGS: + MetricsHelper.sendEvent(MetricsHelper.Categories.PROVIDER_STATE_CHANGES, + action, MetricsHelper.State.SETTINGS, field); + break; + } + } +} diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java index f5d3b9dc8..4f473d15a 100644 --- a/src/com/android/dialer/settings/DialerSettingsActivity.java +++ b/src/com/android/dialer/settings/DialerSettingsActivity.java @@ -1,13 +1,16 @@ package com.android.dialer.settings; import android.app.PendingIntent; +import android.app.Activity; +import android.app.AlertDialog; import android.content.ComponentName; +import android.content.DialogInterface; +import android.content.res.Resources; import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import android.util.Log; import android.widget.CompoundButton; import android.widget.Switch; -import com.android.dialer.DialerApplication; import com.android.phone.common.ambient.AmbientConnection; import com.android.phone.common.incall.CallMethodHelper; import com.android.phone.common.incall.CallMethodInfo; @@ -30,7 +33,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; -import android.preference.PreferenceActivity.Header; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -43,6 +45,8 @@ import android.widget.ListAdapter; import android.widget.TextView; import com.android.dialer.R; +import com.android.dialer.callerinfo.CallerInfoProviderPicker; +import com.android.dialer.util.MetricsHelper; import java.util.ArrayList; import java.util.HashMap; @@ -60,7 +64,7 @@ public class DialerSettingsActivity extends PreferenceActivity { private static final String SETTINGS_INTENT = "settings_intent"; private static final int OWNER_HANDLE_ID = 0; - private CallerInfoHelper.ResolvedProvider mSelectProvider; + private CallerInfoHelper.ResolvedProvider mSelectedProvider; private ProviderInfo mSelectedProviderInfo; private boolean mPickerResult; @@ -94,10 +98,10 @@ public class DialerSettingsActivity extends PreferenceActivity { if (CallerInfoHelper.getInstalledProviders(this).length > 0) { CallerInfoHelper.ResolvedProvider[] providers = CallerInfoHelper.getInstalledProviders(this); - mSelectProvider = providers[0]; - if (mSelectProvider != null ) { + mSelectedProvider = providers[0]; + if (mSelectedProvider != null ) { mSelectedProviderInfo = - CallerInfoHelper.getProviderInfo(this, mSelectProvider.getComponent()); + CallerInfoHelper.getProviderInfo(this, mSelectedProvider.getComponent()); } } super.onCreate(savedInstanceState); @@ -155,6 +159,26 @@ public class DialerSettingsActivity extends PreferenceActivity { } } + if (mSelectedProvider != null && mSelectedProviderInfo != null) { + final Header callInfoHeader = new Header(); + callInfoHeader.title = mSelectedProviderInfo.getTitle(); + callInfoHeader.id = R.id.callerinfo_provider; + int resId = mSelectedProviderInfo.hasProperty(ProviderInfo.PROPERTY_SUPPORTS_SPAM) ? + R.string.callerinfo_provider_summary : R.string.callerinfo_provider_summary_no_spam; + callInfoHeader.summaryRes = resId; + target.add(callInfoHeader); + + final Header silenceSpamHeader = new Header(); + silenceSpamHeader.titleRes = R.string.silence_spam_title; + silenceSpamHeader.summaryRes = R.string.silence_spam_summary; + target.add(silenceSpamHeader); + + final Header blockHidden = new Header(); + blockHidden.titleRes = R.string.block_hidden_title; + blockHidden.summaryRes = R.string.block_hidden_summary; + target.add(blockHidden); + } + Header speedDialHeader = new Header(); Intent speedDialIntent = new Intent("com.android.phone.action.SPEED_DIAL_SETTINGS"); speedDialHeader.titleRes = R.string.speed_dial_settings; @@ -225,7 +249,7 @@ public class DialerSettingsActivity extends PreferenceActivity { } else { // We don't have access to the hidden getHeaders() method, so grab the headers from // the intended adapter and then replace it with our own. - mHeaderAdapter = new HeaderAdapter(this, mCurrentHeaders, mSelectProvider); + mHeaderAdapter = new HeaderAdapter(this, mCurrentHeaders, mSelectedProvider); super.setListAdapter(mHeaderAdapter); } } @@ -240,6 +264,27 @@ public class DialerSettingsActivity extends PreferenceActivity { protected void onResume() { super.onResume(); if (mHeaderAdapter != null) { + if (!mPickerResult && CallerInfoHelper.getActiveProviderPackage(this) != null) { + PendingResult<IsAuthenticatedResult> result = + CallerInfoServices.CallerInfoApi.isAuthenticated( + AmbientConnection.CLIENT.get(this)); + result.setResultCallback(new ResultCallback<IsAuthenticatedResult>() { + @Override + public void onResult(IsAuthenticatedResult isAuthenticatedResult) { + if (!isAuthenticatedResult.getIsAuthenticated()) { + CallerInfoHelper.setActiveProvider(DialerSettingsActivity.this, null); + } + if (mHeaderAdapter != null) { + DialerSettingsActivity.this.runOnUiThread(new Runnable() { + @Override + public void run() { + mHeaderAdapter.notifyDataSetChanged(); + } + }); + } + } + }); + } mPickerResult = false; mHeaderAdapter.notifyDataSetChanged(); } @@ -282,9 +327,68 @@ public class DialerSettingsActivity extends PreferenceActivity { Header header = ((Header) buttonView.getTag()); if (header.extras != null && header.extras.containsKey(COMPONENT_NAME)) { providerStateChanged(header.extras, isChecked, getContext()); + } else if (header.id == R.id.callerinfo_provider) { + ComponentName activeProvider = + CallerInfoHelper.getActiveProviderPackage(getContext()); + // Add active provider check to make sure we don't show dialog + // when loading settings page after provider is already configured. + // This check is too simplistic when we have multiple providers, but + // we need to rework this UI in that case anyway. + if (isChecked && activeProvider == null) { + Intent i = new Intent(getContext(), CallerInfoProviderPicker.class); + i.putExtra(CallerInfoProviderPicker.METRICS_REASON_EXTRA, + CallerInfoProviderPicker.REASON_DIALER_SETTINGS); + ((Activity) getContext()).startActivityForResult(i, 0); + } else if (!isChecked) { + confirmProviderDisable(buttonView); + } + } else if (header.titleRes == R.string.silence_spam_title) { + CallerInfoHelper.setSilenceSpamCalls(getContext(), isChecked); + } else if (header.titleRes == R.string.block_hidden_title) { + CallerInfoHelper.setBlockHiddenNumbers(getContext(), isChecked); } } + private void confirmProviderDisable(final CompoundButton buttonView) { + final ProviderInfo providerInfo = CallerInfoHelper.getActiveProviderInfo(getContext()); + final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + + Resources res = getContext().getResources(); + String title = res.getString(R.string.provider_disable_title, providerInfo.getTitle()); + builder.setTitle(title); + + int resId = providerInfo.hasProperty(ProviderInfo.PROPERTY_SUPPORTS_SPAM) ? + R.string.provider_disable_spam_message : R.string.provider_disable_message; + builder.setMessage(res.getString(resId, providerInfo.getTitle())); + builder.setPositiveButton(R.string.callerinfo_provider_auth_yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MetricsHelper.Field field = new MetricsHelper.Field( + MetricsHelper.Fields.PROVIDER_PACKAGE_NAME, + providerInfo.getPackageName()); + CallerInfoHelper.setActiveProvider(getContext(), null); + MetricsHelper.sendEvent(MetricsHelper.Categories.PROVIDER_STATE_CHANGES, + MetricsHelper.Actions.PROVIDER_DISABLED, + MetricsHelper.State.SETTINGS, field); + } + }); + builder.setNegativeButton(R.string.pause_prompt_no, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + setCheckedStateWithoutTriggeringListener(buttonView, true); + } + }); + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + setCheckedStateWithoutTriggeringListener(buttonView, true); + } + }); + builder.show(); + } + private void setCheckedStateWithoutTriggeringListener(CompoundButton button, boolean state) { button.setOnCheckedChangeListener(null); @@ -298,6 +402,18 @@ public class DialerSettingsActivity extends PreferenceActivity { setCheckedStateWithoutTriggeringListener(switchButton, header.extras.getInt(COMPONENT_STATUS) == PluginStatus.ENABLED); + } else if (header.id == R.id.callerinfo_provider) { + ComponentName activeProvider = CallerInfoHelper.getActiveProviderPackage + (getContext()); + boolean checked = activeProvider != null + && activeProvider.equals(mSelectProvider.getComponent()); + setCheckedStateWithoutTriggeringListener(switchButton, checked); + } else if (header.titleRes == R.string.silence_spam_title) { + setCheckedStateWithoutTriggeringListener(switchButton, + CallerInfoHelper.shouldSilenceSpamCalls(getContext())); + } else if (header.titleRes == R.string.block_hidden_title) { + setCheckedStateWithoutTriggeringListener(switchButton, + CallerInfoHelper.shouldBlockHiddenNumbers(getContext())); } } @@ -322,6 +438,9 @@ public class DialerSettingsActivity extends PreferenceActivity { public static int getHeaderType(Header header) { if (header.extras != null && header.extras.containsKey(COMPONENT_NAME)) { return HEADER_TYPE_SWITCH; + } else if (header.id == R.id.callerinfo_provider || header.titleRes == R.string + .silence_spam_title || header.titleRes == R.string.block_hidden_title) { + return HEADER_TYPE_SWITCH; } else { return HEADER_TYPE_NORMAL; } diff --git a/src/com/android/dialer/util/MetricsHelper.java b/src/com/android/dialer/util/MetricsHelper.java new file mode 100644 index 000000000..3881563ce --- /dev/null +++ b/src/com/android/dialer/util/MetricsHelper.java @@ -0,0 +1,144 @@ +package com.android.dialer.util; + +import android.content.ContentValues; +import android.util.Log; +import com.android.dialer.DialerApplication; +import com.android.phone.common.ambient.AmbientConnection; +import com.cyanogen.ambient.analytics.AnalyticsApi; +import com.cyanogen.ambient.analytics.AnalyticsServices; +import com.cyanogen.ambient.analytics.Event; +import com.cyanogen.ambient.common.api.AmbientApiClient; + +import java.util.AbstractMap; + +public class MetricsHelper { + + private static final String TAG = MetricsHelper.class.getSimpleName(); + private static final boolean DEBUG = false; + + private static final String CATEGORY_BASE = "dialernext.callerinfo."; + + public enum Categories { + PROVIDER_STATE_CHANGES("provider_state_change"), + BLOCKED_CALLS("blocked_calls"), + PROVIDER_PROVIDED_INFORMATION("provider_provided_information"); + + private String mValue; + Categories(String s) { + mValue = CATEGORY_BASE + s; + } + public String value() { + return mValue; + } + }; + + public enum Actions { + BLOCK_CALL("block_call"), + BLOCK_SPAM_CALL("block_and_report_call"), + ANSWERED_CALL("answered_call"), + DECLINED_CALL("declined_call"), + OPTED_IN("opted_in"), + OPTED_OUT("opted_out"), + PROVIDED_INFORMATION("provided_information"), + PROVIDER_DISABLED("provider_disabled"); + + private String mValue; + Actions(String s) { + mValue = s; + } + public String value() { + return mValue; + } + }; + + public enum State { + FIRST_LAUNCH_DIALER("first_launch_dialer"), + AFTER_CALL_ENDED("after_call_ended"), + AFTER_FINAL_PROMPT("after_final_prompt"), + INCALL_SCREEN("incall_screen"), + CONTACT_CARD("contact_card"), + INCALL_NOTIFICATION("incall_notification"), + AFTER_OPTING_IN("after_opting_in"), + AFTER_OPTING_OUT("after_opting_out"), + CALL_LOG("call_log"), + INCOMING_CALL("incoming_call"), + OUTGOING_CALL("outgoing_call"), + SETTINGS("settings"); + + private String mValue; + State(String s) { + mValue = s; + } + public String value() { + return mValue; + } + } + + public final static class Fields { + public final static String PROVIDER_PACKAGE_NAME = "provider_package_name"; + public static final String STATE = "state"; + }; + + public static final class Field { + private final String mValue; + private final String mKey; + + public Field(String key, String value) { + mKey = key; + mValue = value; + } + } + + private static MetricsHelper sInstance; + + private DialerApplication mContext; + + private MetricsHelper() {} + + private static synchronized MetricsHelper getInstance() { + if (sInstance == null) { + sInstance = new MetricsHelper(); + } + return sInstance; + } + + public static void init(DialerApplication context) { + MetricsHelper helper = getInstance(); + helper.mContext = context; + } + + private AmbientApiClient getClient() { + if (mContext == null) { + throw new IllegalStateException("initialize() not invoked"); + } + + return AmbientConnection.CLIENT.get(mContext); + } + + private void sendAmbientEvent(Event event) { + if (DEBUG) { + Log.d(TAG, "Event: " + event.toString()); + } + AnalyticsServices.AnalyticsApi.sendEvent(getClient(), event); + } + + public static void sendEvent(Categories category, Actions action, State state) { + sendEvent(category, action, state, (Field[]) null); + } + + public static void sendEvent(Categories category, Actions action, State state, Field... + fields) { + Event.Builder event = new Event.Builder(category.value(), action.value()); + if (fields != null && fields.length > 0) { + for (Field f : fields) { + if (f != null) { + event.addField(f.mKey, f.mValue); + } + } + } + if (state != null) { + event.addField(Fields.STATE, state.value()); + } + getInstance().sendAmbientEvent(event.build()); + } +} |