summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNathanielWaggoner <nwaggoner@cyngn.com>2016-05-17 16:58:48 -0700
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-05-24 18:04:16 -0700
commit560f3a8913457dbdda7fb9b90be9b2bda56b31e3 (patch)
treecaccf363f4ad4908f94a68e5db43426218ac599f /src
parent5f5b6adf23aaf9d39a106a187bb4c1a7f60b03d8 (diff)
downloadandroid_packages_apps_Dialer-560f3a8913457dbdda7fb9b90be9b2bda56b31e3.tar.gz
android_packages_apps_Dialer-560f3a8913457dbdda7fb9b90be9b2bda56b31e3.tar.bz2
android_packages_apps_Dialer-560f3a8913457dbdda7fb9b90be9b2bda56b31e3.zip
Crash Fix When DeepLinkEnabled callback returns to a null Context.
DeepLinkEnabled request wasn't respecting lifecycle and could execute after the context was no longer valid. This cancels the request in onPause() to better respect the lifecycle. OPO-706 Change-Id: I3aa142ef8a749b9b5537b4af7b2c5438f3dcaa1f
Diffstat (limited to 'src')
-rw-r--r--src/com/android/dialer/calllog/CallLogFragment.java5
-rw-r--r--src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java121
2 files changed, 105 insertions, 21 deletions
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 16509e6a8..4b4e21e1e 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -170,6 +170,8 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
@Override
public void onResult(DeepLink.BooleanResult result) {
boolean value = result.getResults();
+ DeepLinkIntegrationManager.getInstance().completeEnabledRequest(
+ mDeepLinkEnabledCallback);
if (isDeepLinkApiEnabled != value) {
mAdapter.mDeepLinkCache.clearCache();
refreshData();
@@ -348,7 +350,6 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
}
}
});
- areDeepLinksEnabled();
fetchCalls();
return view;
}
@@ -397,7 +398,7 @@ public class CallLogFragment extends Fragment implements CallLogQueryHandler.Lis
mVoicemailPlaybackPresenter.onPause();
}
mAdapter.pauseCache();
-
+ DeepLinkIntegrationManager.getInstance().completeEnabledRequest(mDeepLinkEnabledCallback);
DialerDataSubscription.get(getActivity()).unsubscribe(AMBIENT_SUBSCRIPTION_ID);
super.onPause();
diff --git a/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java b/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java
index 971308ca3..257d9ba59 100644
--- a/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java
+++ b/src/com/android/dialer/deeplink/DeepLinkIntegrationManager.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
+import android.util.ArrayMap;
import com.android.phone.common.ambient.AmbientConnection;
import com.cyanogen.ambient.analytics.AnalyticsServices;
@@ -44,6 +45,9 @@ import java.util.List;
public class DeepLinkIntegrationManager {
+ ArrayMap<Object, PendingResult<DeepLink.BooleanResult>> mPendingResultArrayMap =
+ new ArrayMap<Object, PendingResult<DeepLink.BooleanResult>>();
+
public static DeepLinkIntegrationManager getInstance() {
if (sInstance == null) {
sInstance = new DeepLinkIntegrationManager();
@@ -56,19 +60,32 @@ public class DeepLinkIntegrationManager {
private static DeepLinkIntegrationManager sInstance;
private AmbientApiClient mAmbientApiClient;
private DeepLinkApi mApi;
+ private boolean mShouldQueueRequests = false;
+ /**
+ * Initialize the API.
+ * @param ctx Context to use for connecting to the API.
+ */
public void setUp(Context ctx) {
- if(ambientIsAvailable(ctx)) {
+ if (ambientIsAvailable(ctx)) {
+ mShouldQueueRequests = true;
mApi = (DeepLinkApi) DeepLinkServices.API;
mAmbientApiClient = AmbientConnection.CLIENT.get(ctx);
}
}
+ /**
+ * Get the API's preferred Links for the given Uri.
+ * @param callback code to execute when the API has completed its work.
+ * @param category DeepLinkContentType to query for
+ * @param uri The content Uri to ask the API about.
+ * @return Pending result which represents the future completion of the request.
+ */
public PendingResult<DeepLink.DeepLinkResultList> getPreferredLinksFor(
ResultCallback<DeepLink.DeepLinkResultList> callback, DeepLinkContentType category,
Uri uri) {
PendingResult<DeepLink.DeepLinkResultList> result = null;
- if (hasConnectedClient()) {
+ if (mShouldQueueRequests) {
result = mApi.getPreferredLinksForSingleItem(mAmbientApiClient,
DeepLinkApplicationType.NOTE, category, uri);
result.setResultCallback(callback);
@@ -76,11 +93,20 @@ public class DeepLinkIntegrationManager {
return result;
}
+ /**
+ * For the given list of Uri's, find the preferred link for each system supported
+ * ApplicationType
+ *
+ * @param callback code to execute when the API has finished its work.
+ * @param category DeepLinKContentType to query for (calls, emails etc..)
+ * @param uris List of Uri's the search for a preferred set of links against.
+ * @return Pending result which represents the future completion of the request.
+ */
public PendingResult<DeepLink.DeepLinkResultList> getPreferredLinksForList(
ResultCallback<DeepLink.DeepLinkResultList> callback, DeepLinkContentType category,
List<Uri> uris) {
PendingResult<DeepLink.DeepLinkResultList> result = null;
- if (hasConnectedClient()) {
+ if (mShouldQueueRequests) {
result = mApi.getPreferredLinksForList(mAmbientApiClient,
DeepLinkApplicationType.NOTE, category, uris);
result.setResultCallback(callback);
@@ -88,10 +114,15 @@ public class DeepLinkIntegrationManager {
return result;
}
+ /**
+ * Get's the default plugin information for display.
+ * @param callback Code to execute upon completion.
+ * @param category DeepLinkContentType to query for API defaults.
+ */
public void getDefaultPlugin(ResultCallback<DeepLink.StringResultList> callback,
DeepLinkContentType category) {
PendingResult<DeepLink.StringResultList> result = null;
- if (hasConnectedClient()) {
+ if (mShouldQueueRequests) {
result = mApi.getDefaultProviderDisplayInformation(mAmbientApiClient,
DeepLinkApplicationType.NOTE, category,
DeepLinkIntegrationManager.generateCallUri(dummyNumber, dummyTime));
@@ -110,17 +141,26 @@ public class DeepLinkIntegrationManager {
return Uri.parse(CallLog.AUTHORITY + "." + number + "." + time);
}
+ /**
+ * Checks to ensure ambient is installed and working correctly.
+ * @param ctx context to query against
+ * @return true if ambient is available, false otherwise.
+ */
public boolean ambientIsAvailable(Context ctx) {
return CyanogenAmbientUtil.isCyanogenAmbientAvailable(ctx) == CyanogenAmbientUtil.SUCCESS;
}
- private boolean hasConnectedClient() {
- return mAmbientApiClient != null && mAmbientApiClient.isConnected();
- }
-
+ /**
+ * Send a metrics event of your own design.
+ * @param ctx context to execute against
+ * @param categories Event Categories
+ * @param event Event to report
+ * @param params Specific parameters to include in this event, such as source and
+ * destination.
+ */
public void sendEvent(Context ctx, Categories categories, Events event,
HashMap<Parameters, Object> params) {
- if(hasConnectedClient()) {
+ if (mShouldQueueRequests) {
DeepLinkMetricsHelper.sendEvent(ctx, categories, event, params, mAmbientApiClient);
}
}
@@ -145,9 +185,9 @@ public class DeepLinkIntegrationManager {
* View a given note in the application in which it was taken. Also logs metrics events for
* viewing the note.
*
- * @param ctx Context to log metrics against and to start the activity against.
- * @param deepLink The DeepLink for the content to view
- * @param cn The ComponentName to log as the generator of the metrics event.
+ * @param ctx Context to log metrics against and to start the activity against.
+ * @param deepLink The DeepLink for the content to view
+ * @param cn The ComponentName to log as the generator of the metrics event.
*/
public void viewNote(Context ctx, DeepLink deepLink, ComponentName cn) {
if (deepLink != null && deepLink.getAlreadyHasContent()) {
@@ -156,27 +196,70 @@ public class DeepLinkIntegrationManager {
}
}
+ /**
+ * Report metrics events for creating a new DeepLink between applications.
+ *
+ * @param ctx Context to execute against
+ * @param deepLink DeepLink being created
+ * @param cn ComponentName of the package/class which the event originated within.
+ */
public void sendContentSentEvent(Context ctx, DeepLink deepLink, ComponentName cn) {
sendEvent(ctx, deepLink, cn, Categories.USER_ACTIONS, Events.CONTENT_SENT);
}
+ /**
+ * Report metrics events for opening a previously created DeepLink.
+ *
+ * @param ctx Context to execute against
+ * @param deepLink DeepLink being opened
+ * @param cn ComponentName of the package/class which the event originated within.
+ */
public void sendOpeningExistingEvent(Context ctx, DeepLink deepLink, ComponentName cn) {
sendEvent(ctx, deepLink, cn, Categories.USER_ACTIONS, Events.OPENING_EXISTING_LINK);
}
-
+ /**
+ * Opens a preference activity for the DeepLinkApi to allow users to enable/disable
+ * functionality.
+ *
+ * @param deepLinkApplicationType DepeLinkApplicationType to open preferences for.
+ */
public void openDeepLinkPreferences(DeepLinkApplicationType deepLinkApplicationType) {
- if (hasConnectedClient()) {
+ if (mShouldQueueRequests) {
mApi.openDeepLinkPreferences(mAmbientApiClient, deepLinkApplicationType);
}
}
+ /**
+ * Returns true if the given DeepLinkApplicationType is enabled, false if not.
+ *
+ * @param deepLinkApplicationType DeepLinkApplicationType to check the status of
+ * @param callback Code to execute upon completion of the query.
+ */
public void isApplicationTypeEnabled(DeepLinkApplicationType deepLinkApplicationType,
ResultCallback<DeepLink.BooleanResult> callback) {
- if (hasConnectedClient()) {
- PendingResult<DeepLink.BooleanResult> result = mApi.isApplicationTypeEnabled(
- mAmbientApiClient, deepLinkApplicationType);
- result.setResultCallback(callback);
+ if (mShouldQueueRequests) {
+ completeEnabledRequest(callback);
+ PendingResult<DeepLink.BooleanResult> request =
+ mApi.isApplicationTypeEnabled(mAmbientApiClient, deepLinkApplicationType);
+ request.setResultCallback(callback);
+ mPendingResultArrayMap.put(callback, request);
+ }
+ }
+
+ /**
+ * Takes a ResultCallback<?>.toString() as an argument, cancels any pending requests which have
+ * the argument set as the callback method, removes them from the list of callbacks to track.
+ *
+ * The callbacks are tracked from the moment a query is executed against the API and must be
+ * cleaned up when they are completed, or when the application context becomes invalid.
+ *
+ * @param toCancel key to use for removing objects in PendingResultArrayMap.
+ */
+ public void completeEnabledRequest(Object toCancel) {
+ if (mPendingResultArrayMap.containsKey(toCancel)) {
+ mPendingResultArrayMap.get(toCancel).cancel();
+ mPendingResultArrayMap.remove(toCancel);
}
}
-}
+} \ No newline at end of file