summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNathanielWaggoner <nwaggoner@cyngn.com>2016-04-19 17:05:06 -0700
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-04-29 17:59:34 -0700
commitabec0f3ee457d0a60bc5f32940afea343e9ac1c6 (patch)
treec20b87fc022dd49ad00ac323ac5298483d14bcbe /src
parent9d76b667dcc76356cde0c7bf8469cf219b4d1671 (diff)
downloadandroid_packages_apps_Dialer-abec0f3ee457d0a60bc5f32940afea343e9ac1c6.tar.gz
android_packages_apps_Dialer-abec0f3ee457d0a60bc5f32940afea343e9ac1c6.tar.bz2
android_packages_apps_Dialer-abec0f3ee457d0a60bc5f32940afea343e9ac1c6.zip
Dialer DeepLink Integration
NOTES-53 Change-Id: I90fe73dff9615a9955e61700fe9a712e6a5952ed
Diffstat (limited to 'src')
-rw-r--r--src/com/android/dialer/DialerApplication.java3
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java42
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java40
-rw-r--r--src/com/android/dialer/calllog/CallLogListItemViewHolder.java31
-rw-r--r--src/com/android/dialer/calllog/DeepLinkPresenter.java95
-rw-r--r--src/com/android/dialer/calllog/PhoneCallDetailsHelper.java4
-rw-r--r--src/com/android/dialer/calllog/PhoneCallDetailsViews.java15
-rw-r--r--src/com/android/dialer/deeplink/DeepLinkCache.java320
-rw-r--r--src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java164
-rw-r--r--src/com/android/dialer/deeplink/DeepLinkListener.java29
-rw-r--r--src/com/android/dialer/deeplink/DeepLinkRequest.java53
-rw-r--r--src/com/android/dialer/settings/DialerSettingsActivity.java41
12 files changed, 830 insertions, 7 deletions
diff --git a/src/com/android/dialer/DialerApplication.java b/src/com/android/dialer/DialerApplication.java
index e8e52e481..a5d2e33ec 100644
--- a/src/com/android/dialer/DialerApplication.java
+++ b/src/com/android/dialer/DialerApplication.java
@@ -25,7 +25,7 @@ import com.android.dialer.discovery.WifiCallStatusNudgeListener;
import com.android.dialer.incall.InCallMetricsHelper;
import com.android.phone.common.incall.DialerDataSubscription;
import com.android.dialer.util.MetricsHelper;
-
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
public class DialerApplication extends Application {
@@ -48,6 +48,7 @@ public class DialerApplication extends Application {
MetricsHelper.init(this);
WifiCallStatusNudgeListener.init(this);
InCallMetricsHelper.init(this);
+ DeepLinkIntegrationManager.getInstance().setUp(this);
Trace.endSection();
}
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 7ca61204d..d9e2744b6 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -52,10 +52,14 @@ import com.android.dialer.PhoneCallDetails;
import com.android.dialer.R;
import com.android.dialer.contactinfo.ContactInfoCache;
import com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener;
+import com.android.dialer.deeplink.DeepLinkCache;
+import com.android.dialer.deeplink.DeepLinkCache.DeepLinkListener;
+import com.android.dialer.deeplink.DeepLinkRequest;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.PhoneNumberUtil;
import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
+import com.cyanogen.ambient.deeplink.DeepLink;
import com.cyanogen.ambient.incall.extension.OriginCodes;
import com.google.common.annotations.VisibleForTesting;
@@ -98,6 +102,7 @@ public class CallLogAdapter extends GroupingListAdapter
private final CallFetcher mCallFetcher;
protected ContactInfoCache mContactInfoCache;
+ protected DeepLinkCache mDeepLinkCache;
private boolean mIsShowingRecentsTab;
@@ -294,6 +299,13 @@ public class CallLogAdapter extends GroupingListAdapter
}
};
+ protected final DeepLinkListener mDeepLinkListener = new DeepLinkListener() {
+ @Override
+ public void onDeepLinkCacheChanged() {
+ notifyDataSetChanged();
+ }
+ };
+
public CallLogAdapter(
Context context,
CallFetcher callFetcher,
@@ -315,6 +327,7 @@ public class CallLogAdapter extends GroupingListAdapter
mContactInfoCache = new ContactInfoCache(
mContactInfoHelper, mOnContactInfoChangedListener);
+ mDeepLinkCache = new DeepLinkCache(mDeepLinkListener);
if (!PermissionsUtil.hasContactsPermissions(context)) {
mContactInfoCache.disableRequestProcessing();
}
@@ -371,16 +384,19 @@ public class CallLogAdapter extends GroupingListAdapter
public void invalidateCache() {
mContactInfoCache.invalidate();
+ mDeepLinkCache.invalidate();
}
public void startCache() {
if (PermissionsUtil.hasPermission(mContext, android.Manifest.permission.READ_CONTACTS)) {
mContactInfoCache.start();
+ mDeepLinkCache.start();
}
}
public void pauseCache() {
mContactInfoCache.stop();
+ mDeepLinkCache.stop();
mTelecomCallLogCache.reset();
}
@@ -550,7 +566,18 @@ public class CallLogAdapter extends GroupingListAdapter
} else {
views.inCallComponentName = null;
}
+ views.callTimes = getCallTimes(c, count);
+ DeepLink dl = mDeepLinkCache.getValue(number, views.callTimes);
+ if (dl != null && dl != DeepLinkRequest.EMPTY) {
+ views.mDeepLink = dl;
+ views.phoneCallDetailsViews.noteIconView.setVisibility(View.VISIBLE);
+ views.phoneCallDetailsViews.noteIconView.setImageDrawable(dl.getDrawableIcon(mContext));
+ } else {
+ views.mDeepLink = null;
+ views.phoneCallDetailsViews.noteIconView.setVisibility(View.GONE);
+ }
+ views.mDeepLinkPresenter.prepareUi(number);
// Check if the day group has changed and display a header if necessary.
int currentGroup = getDayGroupForCall(views.rowId);
int previousGroup = getPreviousDayGroup(c);
@@ -586,6 +613,21 @@ public class CallLogAdapter extends GroupingListAdapter
mCallLogListItemHelper.setLookupInfoDetails(views, info);
}
+ /**
+ * Returns call times for the given number of items in the cursor
+ */
+ private long[] getCallTimes(Cursor cursor, int count) {
+ int position = cursor.getPosition();
+ long[] callTimes = new long[count];
+ for (int index = 0; index < count; ++index) {
+ callTimes[index] = cursor.getLong(CallLogQuery.DATE);
+ cursor.moveToNext();
+ }
+ cursor.moveToPosition(position);
+ return callTimes;
+ }
+
+
@Override
public int getItemCount() {
return super.getItemCount() + ((isShowingRecentsTab() || mShowPromoCard) ? 1 : 0);
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index aceaea7c0..b6140c702 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -47,8 +47,12 @@ import com.android.dialer.voicemail.VoicemailPlaybackPresenter;
import com.android.dialer.widget.EmptyContentView;
import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
import com.android.dialerbind.ObjectFactory;
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
import com.android.phone.common.incall.CallMethodInfo;
import com.android.phone.common.incall.DialerDataSubscription;
+import com.cyanogen.ambient.common.api.ResultCallback;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import com.cyanogen.ambient.deeplink.applicationtype.DeepLinkApplicationType;
import com.cyanogen.ambient.incall.CallLogConstants;
import java.util.HashMap;
@@ -120,6 +124,10 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
// Exactly same variable is in Fragment as a package private.
private boolean mMenuVisible = true;
+ // track the enabled/disabled status of the DeepLinkApi so we can update the CalLog in onResume
+ // when returning from settings.
+ private boolean isDeepLinkApiEnabled = false;
+
// Default to all calls.
private int mCallTypeFilter = CallLogQueryHandler.CALL_TYPE_ALL;
@@ -153,6 +161,19 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
}
};
+ /* DeepLinkApi global on/off settings check callback. */
+ private ResultCallback<DeepLink.BooleanResult> mDeepLinkEnabledCallback =
+ new ResultCallback<DeepLink.BooleanResult>() {
+ @Override
+ public void onResult(DeepLink.BooleanResult result) {
+ boolean value = result.getResults();
+ if (isDeepLinkApiEnabled != value) {
+ refreshData();
+ }
+ isDeepLinkApiEnabled = value;
+ }
+ };
+
public interface HostInterface {
public void showDialpad();
}
@@ -221,7 +242,6 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
}
mBlockContactPresenter = new BlockContactPresenter(activity, this);
-
boolean isShowingRecentsTab = mLogLimit != NO_LOG_LIMIT || mDateLimit != NO_DATE_LIMIT;
mAdapter = ObjectFactory.newCallLogAdapter(
getActivity(),
@@ -230,6 +250,7 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
mVoicemailPlaybackPresenter,
mBlockContactPresenter,
isShowingRecentsTab);
+ areDeepLinkEnabled();
}
/** Called by the CallLogQueryHandler when the list of calls has been fetched or updated. */
@@ -313,6 +334,15 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
mRecyclerView.setAdapter(mAdapter);
+ mRecyclerView.setRecyclerListener(new RecyclerView.RecyclerListener() {
+ @Override
+ public void onViewRecycled(RecyclerView.ViewHolder holder) {
+ if (holder instanceof CallLogListItemViewHolder) {
+ final CallLogListItemViewHolder views = (CallLogListItemViewHolder) holder;
+ mAdapter.mDeepLinkCache.clearPendingQueries(views.number, views.callTimes);
+ }
+ }
+ });
fetchCalls();
return view;
@@ -348,12 +378,13 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
updateEmptyMessage(mCallTypeFilter);
}
mHasReadCallLogPermission = hasReadCallLogPermission;
-
if (DialerDataSubscription.get(getActivity())
.subscribe(AMBIENT_SUBSCRIPTION_ID, pluginsUpdatedReceiver)) {
refreshData();
mAdapter.startCache();
}
+
+ areDeepLinkEnabled();
}
@Override
@@ -481,6 +512,11 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
}
}
+ private void areDeepLinkEnabled() {
+ DeepLinkIntegrationManager.getInstance().isApplicationTypeEnabled(
+ DeepLinkApplicationType.NOTE, mDeepLinkEnabledCallback);
+ }
+
/**
* Updates the call data and notification state on entering or leaving the call log tab.
*
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index c3e445969..d01cb3159 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -38,6 +38,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.android.dialer.widget.DialerQuickContact;
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
@@ -53,6 +54,7 @@ import com.android.dialer.voicemail.VoicemailPlaybackLayout;
import com.android.phone.common.incall.CallMethodInfo;
import com.android.phone.common.incall.DialerDataSubscription;
import com.android.phone.common.incall.utils.CallMethodFilters;
+import com.cyanogen.ambient.deeplink.DeepLink;
import com.cyanogen.ambient.incall.extension.OriginCodes;
/**
@@ -81,6 +83,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
public final ImageView primaryActionButtonView;
/** DialerQuickContact */
public final DialerQuickContact dialerQuickContact;
+ public DeepLink mDeepLink;
/** The view containing call log item actions. Null until the ViewStub is inflated. */
public View actionsView;
@@ -88,6 +91,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
public VoicemailPlaybackLayout voicemailPlaybackView;
public View callButtonView;
public View videoCallButtonView;
+ public View viewNoteButton;
public View createNewContactButtonView;
public View addToExistingContactButtonView;
public View sendMessageView;
@@ -112,6 +116,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
public long[] callIds;
/**
+ * The time for each call in callIds represented by the current call log entry. Used when the
+ * user views the call log to determine note status
+ */
+ public long[] callTimes;
+
+ /**
* The callable phone number for the current call log entry. Cached here as the call back
* intent is set only when the actions ViewStub is inflated.
*/
@@ -186,6 +196,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
private final CallLogListItemHelper mCallLogListItemHelper;
private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter;
private final BlockContactPresenter mBlockContactPresenter;
+ public final DeepLinkPresenter mDeepLinkPresenter;
private final int mPhotoSize;
@@ -216,6 +227,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
mCallLogListItemHelper = callLogListItemHelper;
mVoicemailPlaybackPresenter = voicemailPlaybackPresenter;
mBlockContactPresenter = blockContactPresenter;
+ mDeepLinkPresenter = new DeepLinkPresenter(mContext);
+ mDeepLinkPresenter.setCallLogViewHolder(this);
mContactInfoHelper = contactInfoHelper;
this.rootView = rootView;
@@ -293,6 +306,9 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
createNewContactButtonView = actionsView.findViewById(R.id.create_new_contact_action);
createNewContactButtonView.setOnClickListener(this);
+ viewNoteButton = actionsView.findViewById(R.id.view_note_action);
+ viewNoteButton.setOnClickListener(this);
+
addToExistingContactButtonView =
actionsView.findViewById(R.id.add_to_existing_contact_action);
addToExistingContactButtonView.setOnClickListener(this);
@@ -382,6 +398,12 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
callButtonView.setVisibility(View.GONE);
}
+ if (mDeepLink != null) {
+ ImageView icon = (ImageView) viewNoteButton.findViewById(R.id.view_note_action_icon);
+ icon.setImageDrawable(mDeepLink.getDrawableIcon(mContext));
+ } else {
+ viewNoteButton.setVisibility(View.GONE);
+ }
// If one of the calls had video capabilities, show the video call button.
if (mTelecomCallLogCache.isVideoEnabled() && canPlaceCallToNumber &&
phoneCallDetailsViews.callTypeIcons.isVideoShown() ||
@@ -559,6 +581,10 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
view in dialog. */
numberType, /* phone number type (e.g. mobile) in second line of contact view */
accountHandle);
+
+ } else if (view.getId() == R.id.view_note_action) {
+ sendOpeningExisitingEvent();
+ mContext.startActivity(mDeepLink.createViewIntent());
} else {
final String inCallAction = (String) view.getTag(R.id.incall_provider_action_type);
if (inCallComponentName != null && !TextUtils.isEmpty(inCallAction)) {
@@ -628,4 +654,9 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder
return viewHolder;
}
+ private void sendOpeningExisitingEvent() {
+ DeepLinkIntegrationManager.getInstance().sendContentSentEvent(mContext, mDeepLink,
+ new ComponentName(mContext, CallLogListItemViewHolder.class));
+ }
+
}
diff --git a/src/com/android/dialer/calllog/DeepLinkPresenter.java b/src/com/android/dialer/calllog/DeepLinkPresenter.java
new file mode 100644
index 000000000..7e25d3b20
--- /dev/null
+++ b/src/com/android/dialer/calllog/DeepLinkPresenter.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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.calllog;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.View;
+
+import com.cyanogen.ambient.common.api.ResultCallback;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import com.cyanogen.ambient.deeplink.DeepLink.DeepLinkResultList;
+import com.cyanogen.ambient.deeplink.linkcontent.DeepLinkContentType;
+import com.cyanogen.ambient.deeplink.applicationtype.DeepLinkApplicationType;
+
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class DeepLinkPresenter {
+
+ private CallLogListItemViewHolder mViews;
+ Context mContext;
+
+ public DeepLinkPresenter(Context context) {
+ mContext = context;
+ }
+ public void setCallLogViewHolder(CallLogListItemViewHolder holder) {
+ mViews = holder;
+ }
+
+ public void handleDeepLink(List<DeepLink> links) {
+ if (links != null) {
+ for (DeepLink link : links) {
+ if (link != null && link.getApplicationType() == DeepLinkApplicationType.NOTE
+ && link.getIcon() != DeepLink.DEFAULT_ICON) {
+ mViews.mDeepLink = link;
+ updateViews();
+ break;
+ }
+ }
+ }
+ }
+
+ public void handleReadyForRequests(String number,
+ ResultCallback<DeepLinkResultList> deepLinkCallback) {
+ if (mViews.mDeepLink == null) {
+ List<Uri> uris = buildCallUris(number);
+ DeepLinkIntegrationManager.getInstance().getPreferredLinksForList(deepLinkCallback,
+ DeepLinkContentType.CALL, uris);
+ } else {
+ updateViews();
+ }
+ }
+
+ private List<Uri> buildCallUris(String number) {
+ List<Uri> uris = new ArrayList<Uri>(mViews.callTimes.length);
+ for (int i = 0; i < mViews.callTimes.length; i++) {
+ uris.add(DeepLinkIntegrationManager.generateCallUri(number, mViews.callTimes[i]));
+ }
+ return uris;
+ }
+
+ private void updateViews() {
+ mViews.phoneCallDetailsViews.noteIconView.setVisibility(View.VISIBLE);
+ mViews.phoneCallDetailsViews.noteIconView.setImageDrawable(
+ mViews.mDeepLink.getDrawableIcon(mContext));
+ }
+
+ private final ResultCallback<DeepLinkResultList> deepLinkCallback = new
+ ResultCallback<DeepLinkResultList>() {
+ @Override
+ public void onResult(DeepLinkResultList deepLinkResult) {
+ handleDeepLink(deepLinkResult.getResults());
+ }
+ };
+
+ public void prepareUi(final String number) {
+ handleReadyForRequests(number, deepLinkCallback);
+ }
+
+}
diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
index df5fe0606..8da402620 100644
--- a/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
+++ b/src/com/android/dialer/calllog/PhoneCallDetailsHelper.java
@@ -134,7 +134,9 @@ public class PhoneCallDetailsHelper {
}
views.nameView.setText(nameText);
-
+ if (views.noteIconView.getDrawable() == null) {
+ views.noteIconView.setVisibility(View.GONE);
+ }
if (isVoicemail && !TextUtils.isEmpty(details.transcription)) {
views.voicemailTranscriptionView.setText(details.transcription);
views.voicemailTranscriptionView.setVisibility(View.VISIBLE);
diff --git a/src/com/android/dialer/calllog/PhoneCallDetailsViews.java b/src/com/android/dialer/calllog/PhoneCallDetailsViews.java
index 94f4411b0..5658b66c1 100644
--- a/src/com/android/dialer/calllog/PhoneCallDetailsViews.java
+++ b/src/com/android/dialer/calllog/PhoneCallDetailsViews.java
@@ -27,6 +27,8 @@ import com.android.dialer.R;
* Encapsulates the views that are used to display the details of a phone call in the call log.
*/
public final class PhoneCallDetailsViews {
+ public final View nameWrapper;
+ public final ImageView noteIconView;
public final TextView nameView;
public final View callTypeView;
public final CallTypeIconsView callTypeIcons;
@@ -34,9 +36,11 @@ public final class PhoneCallDetailsViews {
public final TextView voicemailTranscriptionView;
public final TextView callAccountLabel;
- private PhoneCallDetailsViews(TextView nameView, View callTypeView,
- CallTypeIconsView callTypeIcons, TextView callLocationAndDate,
+ private PhoneCallDetailsViews(View nameContainer, ImageView noteIconView, TextView nameView,
+ View callTypeView, CallTypeIconsView callTypeIcons, TextView callLocationAndDate,
TextView voicemailTranscriptionView, TextView callAccountLabel) {
+ this.nameWrapper = nameContainer;
+ this.noteIconView = noteIconView;
this.nameView = nameView;
this.callTypeView = callTypeView;
this.callTypeIcons = callTypeIcons;
@@ -53,7 +57,10 @@ public final class PhoneCallDetailsViews {
* {@code R.id.call_types}.
*/
public static PhoneCallDetailsViews fromView(View view) {
- return new PhoneCallDetailsViews((TextView) view.findViewById(R.id.name),
+ return new PhoneCallDetailsViews(
+ view.findViewById(R.id.nameWrapper),
+ (ImageView) view.findViewById(R.id.hasNotes),
+ (TextView) view.findViewById(R.id.name),
view.findViewById(R.id.call_type),
(CallTypeIconsView) view.findViewById(R.id.call_type_icons),
(TextView) view.findViewById(R.id.call_location_and_date),
@@ -63,6 +70,8 @@ public final class PhoneCallDetailsViews {
public static PhoneCallDetailsViews createForTest(Context context) {
return new PhoneCallDetailsViews(
+ new View(context),
+ new ImageView(context),
new TextView(context),
new View(context),
new CallTypeIconsView(context),
diff --git a/src/com/android/dialer/deeplink/DeepLinkCache.java b/src/com/android/dialer/deeplink/DeepLinkCache.java
new file mode 100644
index 000000000..068e29c4f
--- /dev/null
+++ b/src/com/android/dialer/deeplink/DeepLinkCache.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2016 CyanogenMod
+ *
+ * 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.deeplink;
+
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.dialer.util.ExpirableCache;
+
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
+
+import com.cyanogen.ambient.common.api.PendingResult;
+import com.cyanogen.ambient.common.api.ResultCallback;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import com.cyanogen.ambient.deeplink.applicationtype.DeepLinkApplicationType;
+import com.cyanogen.ambient.deeplink.linkcontent.DeepLinkContentType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Cache for managing DeepLinks for the CallLogAdapter and anyone else interested in caching
+ * DeepLinks.
+ *
+ * The methods like getValue(String number, long[] calLTimes) and
+ * clearPendingQueries(String number, long[] calLTimes) both assume that callTimes are in order
+ * from mostRecent to eldest, and that this will be the same for a given set of number/call times
+ * each time. This is used for tracking requests and canceling unnecessary ones.
+ *
+ * Expects queries to provide a number and call time.
+ */
+public class DeepLinkCache {
+
+ /**
+ * Listener to be notified when the DeepLinkCache has changed.
+ */
+ public interface DeepLinkListener {
+ /**
+ * A change has occurred in the DeepLinkCache, and previous state may be invalid.
+ */
+ public void onDeepLinkCacheChanged();
+
+ }
+
+ private static final int START_THREAD = 0;
+ private static final int REDRAW = 1;
+ private static final int DEEP_LINK_CACHE_SIZE = 100;
+ private static final int START_PROCESSING_REQUESTS_DELAY_MS = 1000;
+ private static final int PROCESSING_THREAD_THROTTLE_LIMIT = 1000;
+ private DeepLinkListener mDeepLinkListener;
+ private final LinkedList<DeepLinkRequest> mRequests;
+ /**
+ * Track queries that have bene issued to AmbientCore so we can cancel them if the user leaves
+ * a context where they are relevant.
+ */
+ private final HashMap<Uri, PendingResult<DeepLink.DeepLinkResultList>> mPendingRequests;
+ /**
+ * Cache for DeepLink queries we've already completed.
+ */
+ private ExpirableCache<String, DeepLink> mCache;
+
+ private QueryThread mDeepLinkQueryThread;
+ private boolean mRequestProcessingDisabled = false;
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case REDRAW:
+ mDeepLinkListener.onDeepLinkCacheChanged();
+ break;
+ case START_THREAD:
+ startRequestProcessing();
+ break;
+ }
+ }
+ };
+
+ /**
+ * Handles requests for DeepLinks as related to a number and call time.
+ */
+ private class QueryThread extends Thread {
+ private volatile boolean mDone = false;
+ public volatile boolean needRedraw = false;
+
+ public QueryThread() {
+ super("DeepLinkCache.QueryThread");
+ }
+
+ public void stopProcessing() {
+ mDone = true;
+ interrupt();
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ // Check if thread is finished, and if so return immediately.
+ if (mDone) return;
+ // Obtain next request, if any is available.
+ // Keep synchronized section small.
+ DeepLinkRequest req = null;
+ synchronized (mRequests) {
+ if (!mRequests.isEmpty()) {
+ req = mRequests.removeFirst();
+ }
+ }
+ if (req != null) {
+ // Process the request.
+ queryDeepLinks(req);
+ } else {
+ // only update the UI when there are no more requests
+ if (needRedraw) {
+ needRedraw = false;
+ mHandler.sendEmptyMessage(REDRAW);
+ }
+ // Wait until another request is available, or until this
+ // thread is no longer needed (as indicated by being
+ // interrupted).
+ try {
+ synchronized (mRequests) {
+ mRequests.wait(PROCESSING_THREAD_THROTTLE_LIMIT);
+ }
+ } catch (InterruptedException ie) {
+ // Ignore, and attempt to continue processing requests.
+ }
+ }
+ }
+ }
+ }
+
+ public DeepLinkCache(DeepLinkListener listener) {
+ mRequests = new LinkedList<DeepLinkRequest>();
+ mPendingRequests = new HashMap<Uri, PendingResult<DeepLink.DeepLinkResultList>>();
+ mCache = ExpirableCache.create(DEEP_LINK_CACHE_SIZE);
+ mDeepLinkListener = listener;
+ }
+
+ public DeepLink getValue(String number, long[] times) {
+ long mostRecentCall = Long.MIN_VALUE;
+ DeepLink toReturn = null;
+ List<Uri> urisToRequest = new ArrayList<Uri>();
+ boolean immediate = false;
+ // for all calls
+ for (long callTime : times) {
+ // generate the URI
+ Uri uri = DeepLinkIntegrationManager.generateCallUri(number, callTime);
+ String uriString = uri.toString();
+ // hit the cache, do we have a link for this call?
+ ExpirableCache.CachedValue<DeepLink> cachedInfo =
+ mCache.getCachedValue(uriString);
+ // if so is that a null object?
+ DeepLink info = cachedInfo == null ? null : cachedInfo.getValue();
+ if (cachedInfo == null) {
+ // if its null we need to add a uri to our requests
+ mCache.put(uriString, DeepLinkRequest.EMPTY);
+ urisToRequest.add(uri);
+ // if we get any uris that haven't been handled we need to immediately do this query
+ immediate = true;
+ } else if (cachedInfo.isExpired()) {
+ urisToRequest.add(uri);
+ }
+ if (info != null && info != DeepLinkRequest.EMPTY && callTime > mostRecentCall) {
+ mostRecentCall = callTime;
+ toReturn = info;
+ }
+ }
+ // issue new requests for any uri's we haven't handled previously
+ if (urisToRequest.size() > 0) {
+ enqueueRequest(urisToRequest, immediate);
+ }
+ return toReturn;
+ }
+
+
+ protected void enqueueRequest(List<Uri> uris, boolean immediate) {
+ DeepLinkRequest request = new DeepLinkRequest(uris);
+ synchronized (mRequests) {
+ if (!mRequests.contains(request)) {
+ mRequests.add(request);
+ mRequests.notifyAll();
+ }
+ }
+ if (immediate) {
+ startRequestProcessing();
+ }
+ }
+
+
+ private synchronized void startRequestProcessing() {
+ if (mRequestProcessingDisabled) return;
+
+ // If a thread is already started, don't start another.
+ if (mDeepLinkQueryThread != null) {
+ return;
+ }
+
+ mDeepLinkQueryThread = new QueryThread();
+ mDeepLinkQueryThread.setPriority(Thread.MIN_PRIORITY);
+ mDeepLinkQueryThread.start();
+ }
+
+ /**
+ * Stops the background thread that processes updates and cancels any
+ * pending requests to start it.
+ */
+ private synchronized void stopRequestProcessing() {
+ // Remove any pending requests to start the processing thread.
+ mHandler.removeMessages(START_THREAD);
+ if (mDeepLinkQueryThread != null) {
+ // Stop the thread; we are finished with it.
+ mDeepLinkQueryThread.stopProcessing();
+ mDeepLinkQueryThread = null;
+ mRequests.clear();
+ mPendingRequests.clear();
+ }
+ }
+
+ /**
+ * Expire the cache in its entirety.
+ */
+ public void invalidate() {
+ mCache.expireAll();
+ stopRequestProcessing();
+ }
+
+ /**
+ * After a delay, start the thread to begin processing requests. We perform lookups on a
+ * background thread, but this must be called to indicate the thread should be running.
+ */
+ public void start() {
+ // Schedule a thread-creation message if the thread hasn't been created yet, as an
+ // optimization to queue fewer messages.
+ if (mDeepLinkQueryThread == null) {
+ // TODO: Check whether this delay before starting to process is necessary.
+ mHandler.sendEmptyMessageDelayed(START_THREAD, START_PROCESSING_REQUESTS_DELAY_MS);
+ }
+ }
+
+ /**
+ * Stops the thread and clears the queue of messages to process. This cleans up the thread
+ * for lookups so that it is not perpetually running.
+ */
+ public void stop() {
+ stopRequestProcessing();
+ }
+
+ ResultCallback<DeepLink.DeepLinkResultList> mDeepLinkCallback =
+ new ResultCallback<DeepLink.DeepLinkResultList>() {
+ @Override
+ public void onResult(DeepLink.DeepLinkResultList result) {
+ if (result.getResults() != null) {
+ handleDeepLinkResults(result.getResults());
+ }
+ }
+ };
+
+ private void handleDeepLinkResults(List<DeepLink> results) {
+ for (DeepLink link : results) {
+ if (shouldPlaceLinkInCache(link)) {
+ mCache.put(link.getUri().toString(), link);
+ if (mDeepLinkQueryThread != null && mPendingRequests.size() <= 0) {
+ mDeepLinkQueryThread.needRedraw = true;
+ }
+ }
+ }
+ }
+
+ private boolean shouldPlaceLinkInCache(DeepLink link) {
+ return link != null && link.getApplicationType() == DeepLinkApplicationType.NOTE &&
+ link.getAlreadyHasContent() && !linkExistsInCache(link);
+ }
+
+ private boolean linkExistsInCache(DeepLink link) {
+ DeepLink oldLink = mCache.getPossiblyExpired(link.getUri().toString());
+ return link.equals(oldLink);
+ }
+
+ /**
+ * Kick off an ambient query for a given request.
+ *
+ * @param request - the DeepLinkRequest to query against.
+ */
+ private void queryDeepLinks(DeepLinkRequest request) {
+ synchronized (mPendingRequests) {
+ mPendingRequests.put(request.getUris().get(0),
+ DeepLinkIntegrationManager.getInstance().getPreferredLinksForList(
+ mDeepLinkCallback, DeepLinkContentType.CALL, request.getUris()));
+ }
+ }
+
+ public void clearPendingQueries(String number, long[] calltimes) {
+ synchronized (mPendingRequests) {
+ Uri uri = DeepLinkIntegrationManager.generateCallUri(number, calltimes[0]);
+ if (mPendingRequests.containsKey(uri)) {
+ PendingResult<DeepLink.DeepLinkResultList> request = mPendingRequests.remove(uri);
+ if (request!= null) {
+ request.cancel();
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java b/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java
new file mode 100644
index 000000000..8d729a1e9
--- /dev/null
+++ b/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 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.deeplink;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.CallLog;
+
+import com.android.phone.common.ambient.AmbientConnection;
+import com.cyanogen.ambient.analytics.AnalyticsServices;
+import com.cyanogen.ambient.common.ConnectionResult;
+import com.cyanogen.ambient.common.CyanogenAmbientUtil;
+import com.cyanogen.ambient.common.api.AmbientApiClient;
+import com.cyanogen.ambient.common.api.PendingResult;
+import com.cyanogen.ambient.common.api.ResultCallback;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import com.cyanogen.ambient.deeplink.DeepLinkApi;
+import com.cyanogen.ambient.deeplink.DeepLinkServices;
+import com.cyanogen.ambient.deeplink.applicationtype.DeepLinkApplicationType;
+import com.cyanogen.ambient.deeplink.linkcontent.DeepLinkContentType;
+import com.cyanogen.ambient.deeplink.metrics.DeepLinkMetricsHelper;
+import com.cyanogen.ambient.deeplink.metrics.DeepLinkMetricsHelper.Categories;
+import com.cyanogen.ambient.deeplink.metrics.DeepLinkMetricsHelper.Events;
+import com.cyanogen.ambient.deeplink.metrics.DeepLinkMetricsHelper.Parameters;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class DeepLinkIntegrationManager {
+
+ public static DeepLinkIntegrationManager getInstance() {
+ if (sInstance == null) {
+ sInstance = new DeepLinkIntegrationManager();
+ }
+ return sInstance;
+ }
+
+ private String dummyNumber = "00000000";
+ private long dummyTime = 0l;
+ private static DeepLinkIntegrationManager sInstance;
+ private AmbientApiClient mAmbientApiClient;
+ private DeepLinkApi mApi;
+ private volatile boolean mConnected = false;
+
+ public void setUp(Context ctx) {
+ if(ambientIsAvailable(ctx)) {
+ mApi = (DeepLinkApi) DeepLinkServices.API;
+ mAmbientApiClient = AmbientConnection.CLIENT.get(ctx);
+ }
+ }
+
+ public PendingResult<DeepLink.DeepLinkResultList> getPreferredLinksFor(
+ ResultCallback<DeepLink.DeepLinkResultList> callback, DeepLinkContentType category,
+ Uri uri) {
+ PendingResult<DeepLink.DeepLinkResultList> result = null;
+ if (mAmbientApiClient.isConnected()) {
+ result = mApi.getPreferredLinksForSingleItem(mAmbientApiClient,
+ DeepLinkApplicationType.NOTE, category, uri);
+ result.setResultCallback(callback);
+ }
+ return result;
+ }
+
+ public PendingResult<DeepLink.DeepLinkResultList> getPreferredLinksForList(
+ ResultCallback<DeepLink.DeepLinkResultList> callback, DeepLinkContentType category,
+ List<Uri> uris) {
+ PendingResult<DeepLink.DeepLinkResultList> result = null;
+ if (mAmbientApiClient.isConnected()) {
+ result = mApi.getPreferredLinksForList(mAmbientApiClient,
+ DeepLinkApplicationType.NOTE, category, uris);
+ result.setResultCallback(callback);
+ }
+ return result;
+ }
+
+ public void getDefaultPlugin(ResultCallback<DeepLink.StringResultList> callback,
+ DeepLinkContentType category) {
+ PendingResult<DeepLink.StringResultList> result = null;
+ if (mAmbientApiClient.isConnected()) {
+ result = mApi.getDefaultProviderDisplayInformation(mAmbientApiClient,
+ DeepLinkApplicationType.NOTE, category,
+ DeepLinkIntegrationManager.generateCallUri(dummyNumber, dummyTime));
+ result.setResultCallback(callback);
+ }
+ }
+
+ /**
+ * Generate a uri which will identify the call for a given number and timestamp
+ *
+ * @param number - the phone number dialed
+ * @param time - the time the call occured
+ * @return Uri identifying the call.
+ */
+ public static Uri generateCallUri(String number, long time) {
+ return Uri.parse(CallLog.AUTHORITY + "." + number + "." + time);
+ }
+
+ public boolean ambientIsAvailable(Context ctx) {
+ return CyanogenAmbientUtil.isCyanogenAmbientAvailable(ctx) == CyanogenAmbientUtil.SUCCESS;
+ }
+
+ public void sendEvent(Context ctx, Categories categories, Events event,
+ HashMap<Parameters, Object> params) {
+ if(mAmbientApiClient.isConnected()) {
+ DeepLinkMetricsHelper.sendEvent(ctx, categories, event, params, mAmbientApiClient);
+ }
+ }
+
+ private void sendEvent(Context ctx, DeepLink deepLink, ComponentName cn,
+ Categories category, Events event) {
+
+ HashMap<Parameters, Object>
+ parameters = new HashMap<Parameters, Object>();
+
+ parameters.put(Parameters.SOURCE, cn.flattenToString());
+ parameters.put(Parameters.DESTINATION, deepLink.getPackageName());
+ parameters.put(Parameters.CONTENT_TYPE,
+ deepLink.getDeepLinkContentType());
+ parameters.put(Parameters.DEST_APPLICATION_TYPE,
+ deepLink.getApplicationType());
+ parameters.put(Parameters.CONTENT_UID, deepLink.getUri().toString());
+ sendEvent(ctx, category, event, parameters);
+ }
+
+ public void sendContentSentEvent(Context ctx, DeepLink deepLink, ComponentName cn) {
+ sendEvent(ctx, deepLink, cn, Categories.USER_ACTIONS, Events.CONTENT_SENT);
+ }
+
+ public void sendOpeningExistingEvent(Context ctx, DeepLink deepLink, ComponentName cn) {
+ sendEvent(ctx, deepLink, cn, Categories.USER_ACTIONS, Events.OPENING_EXISTING_LINK);
+ }
+
+
+ public void openDeepLinkPreferences(DeepLinkApplicationType deepLinkApplicationType) {
+ if (mAmbientApiClient.isConnected()) {
+ mApi.openDeepLinkPreferences(mAmbientApiClient, deepLinkApplicationType);
+ }
+ }
+
+ public void isApplicationTypeEnabled(DeepLinkApplicationType deepLinkApplicationType,
+ ResultCallback<DeepLink.BooleanResult> callback) {
+ if (mAmbientApiClient.isConnected()) {
+ PendingResult<DeepLink.BooleanResult> result = mApi.isApplicationTypeEnabled(
+ mAmbientApiClient, deepLinkApplicationType);
+ result.setResultCallback(callback);
+ }
+ }
+}
diff --git a/src/com/android/dialer/deeplink/DeepLinkListener.java b/src/com/android/dialer/deeplink/DeepLinkListener.java
new file mode 100644
index 000000000..65ebec708
--- /dev/null
+++ b/src/com/android/dialer/deeplink/DeepLinkListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 CyanogenMod
+ *
+ * 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.deeplink;
+
+/**
+ * Listener to be notified when the DeepLinkCache has changed.
+ */
+public interface DeepLinkListener {
+
+ /**
+ * A change has occurred in the DeepLinkCache, and previous state may be invalid.
+ */
+ public void onDeepLinkCacheChanged();
+
+}
diff --git a/src/com/android/dialer/deeplink/DeepLinkRequest.java b/src/com/android/dialer/deeplink/DeepLinkRequest.java
new file mode 100644
index 000000000..5d570f2d7
--- /dev/null
+++ b/src/com/android/dialer/deeplink/DeepLinkRequest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 CyanogenMod
+ *
+ * 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.deeplink;
+
+import android.net.Uri;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import java.util.List;
+
+public class DeepLinkRequest {
+ public static final DeepLink EMPTY = new DeepLink(null, null, null, null, -1, -1, null, null,
+ false);
+ /**
+ * The uris for this set of number and times
+ */
+ private List<Uri> mUris;
+
+ public DeepLinkRequest(List<Uri> uris) {
+ mUris = uris;
+ }
+
+ public List<Uri> getUris() {
+ return mUris;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (!(obj instanceof DeepLinkRequest)) return false;
+
+ DeepLinkRequest other = (DeepLinkRequest) obj;
+ return mUris.equals(other.mUris);
+ }
+
+ @Override
+ public int hashCode() {
+ return mUris.hashCode();
+ }
+}
diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java
index 27fa53416..31df4b238 100644
--- a/src/com/android/dialer/settings/DialerSettingsActivity.java
+++ b/src/com/android/dialer/settings/DialerSettingsActivity.java
@@ -11,6 +11,8 @@ import android.preference.PreferenceScreen;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.Switch;
+
+import com.android.dialer.deeplink.DeepLinkIntegrationManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.phone.common.ambient.AmbientConnection;
import com.android.phone.common.incall.DialerDataSubscription;
@@ -21,6 +23,9 @@ import com.cyanogen.ambient.callerinfo.util.CallerInfoHelper;
import com.cyanogen.ambient.callerinfo.util.ProviderInfo;
import com.cyanogen.ambient.common.api.PendingResult;
import com.cyanogen.ambient.common.api.ResultCallback;
+import com.cyanogen.ambient.deeplink.DeepLink;
+import com.cyanogen.ambient.deeplink.applicationtype.DeepLinkApplicationType;
+import com.cyanogen.ambient.deeplink.linkcontent.DeepLinkContentType;
import com.cyanogen.ambient.plugin.PluginStatus;
import com.cyanogen.ambient.incall.util.InCallHelper;
import com.google.common.collect.Lists;
@@ -72,6 +77,7 @@ public class DialerSettingsActivity extends PreferenceActivity {
PreferenceScreen mPreferenceScreen;
List<CallMethodInfo> mCallProviders = new ArrayList<>();
List<Header> mCurrentHeaders = Lists.newArrayList();
+ List<String> mDeepLinkPluginInfo;
private static final String AMBIENT_SUBSCRIPTION_ID = "DialerSettingsActivity";
@@ -83,6 +89,22 @@ public class DialerSettingsActivity extends PreferenceActivity {
}
};
+ private ResultCallback<DeepLink.StringResultList> mDeepLinkCallback =
+ new ResultCallback<DeepLink.StringResultList>() {
+ @Override
+ public void onResult(DeepLink.StringResultList result) {
+ List<String> results = result.getResults();
+ if (results != null && results.size() > 0) {
+ deepLinkUpdated(results);
+ }
+ }
+ };
+
+ private void deepLinkUpdated(List<String> deepLinkPluginInfo) {
+ mDeepLinkPluginInfo = deepLinkPluginInfo;
+ invalidateHeaders();
+ }
+
private void providersUpdated(HashMap<ComponentName, CallMethodInfo> callMethodInfos) {
mCallProviders.clear();
mCallProviders.addAll(callMethodInfos.values());
@@ -106,6 +128,9 @@ public class DialerSettingsActivity extends PreferenceActivity {
CallerInfoHelper.getProviderInfo(this, mSelectedProvider.getComponent());
}
}
+ DeepLinkIntegrationManager.getInstance().getDefaultPlugin(mDeepLinkCallback,
+ DeepLinkContentType.CALL);
+
super.onCreate(savedInstanceState);
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
}
@@ -224,6 +249,13 @@ public class DialerSettingsActivity extends PreferenceActivity {
}
}
+ if (mDeepLinkPluginInfo != null) {
+ Header noteHeader = new Header();
+ noteHeader.title = mDeepLinkPluginInfo.get(0);
+ noteHeader.summaryRes = R.string.note_mod_settings_summary;
+ target.add(noteHeader);
+ }
+
// invalidateHeaders does not rebuild
// the list properly, so if an adapter is present already
// then we've invalidated and need make sure we notify the list.
@@ -571,4 +603,13 @@ public class DialerSettingsActivity extends PreferenceActivity {
asyncTask.execute(status);
return status;
}
+
+ @Override
+ public void onHeaderClick(Header header, int position) {
+ super.onHeaderClick(header, position);
+ if (header.summaryRes == R.string.note_mod_settings_summary) {
+ DeepLinkIntegrationManager.getInstance().openDeepLinkPreferences
+ (DeepLinkApplicationType.NOTE);
+ }
+ }
}