Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 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.server.pm; |
| 18 | |
Patrick Baumann | 3e0b8ee | 2018-04-26 12:03:15 -0700 | [diff] [blame] | 19 | import static android.content.Intent.FLAG_ACTIVITY_MATCH_EXTERNAL; |
| 20 | |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 21 | import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE; |
| 22 | import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO; |
| 23 | import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; |
| 24 | import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_DELAY_MS; |
| 25 | import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_STATUS; |
| 26 | |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 27 | import android.annotation.IntDef; |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 28 | import android.annotation.NonNull; |
| 29 | import android.annotation.Nullable; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 30 | import android.app.ActivityManager; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 31 | import android.app.PendingIntent; |
| 32 | import android.content.ComponentName; |
| 33 | import android.content.Context; |
| 34 | import android.content.IIntentSender; |
| 35 | import android.content.Intent; |
| 36 | import android.content.IntentFilter; |
| 37 | import android.content.IntentSender; |
| 38 | import android.content.pm.ActivityInfo; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 39 | import android.content.pm.InstantAppRequest; |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 40 | import android.content.pm.AuxiliaryResolveInfo; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 41 | import android.content.pm.InstantAppIntentFilter; |
| 42 | import android.content.pm.InstantAppResolveInfo; |
| 43 | import android.content.pm.InstantAppResolveInfo.InstantAppDigest; |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 44 | import android.metrics.LogMaker; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 45 | import android.net.Uri; |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 46 | import android.os.Build; |
Chad Brubaker | 0606861 | 2017-04-06 09:43:47 -0700 | [diff] [blame] | 47 | import android.os.Bundle; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 48 | import android.os.Handler; |
| 49 | import android.os.RemoteException; |
| 50 | import android.util.Log; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 51 | import android.util.Slog; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 52 | |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 53 | import com.android.internal.logging.MetricsLogger; |
| 54 | import com.android.internal.logging.nano.MetricsProto; |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 55 | import com.android.server.pm.InstantAppResolverConnection.ConnectionException; |
| 56 | import com.android.server.pm.InstantAppResolverConnection.PhaseTwoCallback; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 57 | |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 58 | import java.lang.annotation.Retention; |
| 59 | import java.lang.annotation.RetentionPolicy; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 60 | import java.util.ArrayList; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 61 | import java.util.Arrays; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 62 | import java.util.Collections; |
| 63 | import java.util.Iterator; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 64 | import java.util.List; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 65 | import java.util.Set; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 66 | import java.util.UUID; |
| 67 | |
| 68 | /** @hide */ |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 69 | public abstract class InstantAppResolver { |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 70 | private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE; |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 71 | private static final String TAG = "PackageManager"; |
| 72 | |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 73 | private static final int RESOLUTION_SUCCESS = 0; |
| 74 | private static final int RESOLUTION_FAILURE = 1; |
| 75 | /** Binding to the external service timed out */ |
| 76 | private static final int RESOLUTION_BIND_TIMEOUT = 2; |
| 77 | /** The call to retrieve an instant application response timed out */ |
| 78 | private static final int RESOLUTION_CALL_TIMEOUT = 3; |
| 79 | |
| 80 | @IntDef(flag = true, prefix = { "RESOLUTION_" }, value = { |
| 81 | RESOLUTION_SUCCESS, |
| 82 | RESOLUTION_FAILURE, |
| 83 | RESOLUTION_BIND_TIMEOUT, |
| 84 | RESOLUTION_CALL_TIMEOUT, |
| 85 | }) |
| 86 | @Retention(RetentionPolicy.SOURCE) |
| 87 | public @interface ResolutionStatus {} |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 88 | |
| 89 | private static MetricsLogger sMetricsLogger; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 90 | |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 91 | private static MetricsLogger getLogger() { |
| 92 | if (sMetricsLogger == null) { |
| 93 | sMetricsLogger = new MetricsLogger(); |
| 94 | } |
| 95 | return sMetricsLogger; |
| 96 | } |
| 97 | |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 98 | /** |
| 99 | * Returns an intent with potential PII removed from the original intent. Fields removed |
| 100 | * include extras and the host + path of the data, if defined. |
| 101 | */ |
| 102 | public static Intent sanitizeIntent(Intent origIntent) { |
| 103 | final Intent sanitizedIntent; |
| 104 | sanitizedIntent = new Intent(origIntent.getAction()); |
| 105 | Set<String> categories = origIntent.getCategories(); |
| 106 | if (categories != null) { |
| 107 | for (String category : categories) { |
| 108 | sanitizedIntent.addCategory(category); |
| 109 | } |
| 110 | } |
| 111 | Uri sanitizedUri = origIntent.getData() == null |
| 112 | ? null |
| 113 | : Uri.fromParts(origIntent.getScheme(), "", ""); |
| 114 | sanitizedIntent.setDataAndType(sanitizedUri, origIntent.getType()); |
| 115 | sanitizedIntent.addFlags(origIntent.getFlags()); |
| 116 | sanitizedIntent.setPackage(origIntent.getPackage()); |
| 117 | return sanitizedIntent; |
| 118 | } |
| 119 | |
| 120 | public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne( |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 121 | InstantAppResolverConnection connection, InstantAppRequest requestObj) { |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 122 | final long startTime = System.currentTimeMillis(); |
| 123 | final String token = UUID.randomUUID().toString(); |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 124 | if (DEBUG_INSTANT) { |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 125 | Log.d(TAG, "[" + token + "] Phase1; resolving"); |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 126 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 127 | final Intent origIntent = requestObj.origIntent; |
| 128 | final Intent sanitizedIntent = sanitizeIntent(origIntent); |
| 129 | |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 130 | AuxiliaryResolveInfo resolveInfo = null; |
| 131 | @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS; |
| 132 | try { |
| 133 | final List<InstantAppResolveInfo> instantAppResolveInfoList = |
Patrick Baumann | 4db6bc1 | 2018-02-06 09:55:36 -0800 | [diff] [blame] | 134 | connection.getInstantAppResolveInfoList(sanitizedIntent, |
| 135 | requestObj.digest.getDigestPrefixSecure(), token); |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 136 | if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { |
| 137 | resolveInfo = InstantAppResolver.filterInstantAppIntent( |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 138 | instantAppResolveInfoList, origIntent, requestObj.resolvedType, |
Patrick Baumann | 4db6bc1 | 2018-02-06 09:55:36 -0800 | [diff] [blame] | 139 | requestObj.userId, origIntent.getPackage(), requestObj.digest, token); |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 140 | } |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 141 | } catch (ConnectionException e) { |
| 142 | if (e.failure == ConnectionException.FAILURE_BIND) { |
| 143 | resolutionStatus = RESOLUTION_BIND_TIMEOUT; |
| 144 | } else if (e.failure == ConnectionException.FAILURE_CALL) { |
| 145 | resolutionStatus = RESOLUTION_CALL_TIMEOUT; |
| 146 | } else { |
| 147 | resolutionStatus = RESOLUTION_FAILURE; |
| 148 | } |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 149 | } |
Todd Kennedy | f4c3855 | 2017-06-12 10:33:32 -0700 | [diff] [blame] | 150 | // Only log successful instant application resolution |
Todd Kennedy | 6ebabca | 2017-08-22 10:02:12 -0700 | [diff] [blame] | 151 | if (requestObj.resolveForStart && resolutionStatus == RESOLUTION_SUCCESS) { |
Todd Kennedy | f4c3855 | 2017-06-12 10:33:32 -0700 | [diff] [blame] | 152 | logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, |
| 153 | resolutionStatus); |
| 154 | } |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 155 | if (DEBUG_INSTANT && resolveInfo == null) { |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 156 | if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { |
| 157 | Log.d(TAG, "[" + token + "] Phase1; bind timed out"); |
| 158 | } else if (resolutionStatus == RESOLUTION_CALL_TIMEOUT) { |
| 159 | Log.d(TAG, "[" + token + "] Phase1; call timed out"); |
| 160 | } else if (resolutionStatus != RESOLUTION_SUCCESS) { |
| 161 | Log.d(TAG, "[" + token + "] Phase1; service connection error"); |
| 162 | } else { |
| 163 | Log.d(TAG, "[" + token + "] Phase1; No results matched"); |
| 164 | } |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 165 | } |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 166 | // if the match external flag is set, return an empty resolve info instead of a null result. |
| 167 | if (resolveInfo == null && (origIntent.getFlags() & FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) { |
| 168 | return new AuxiliaryResolveInfo(token, false, createFailureIntent(origIntent, token), |
| 169 | null /* filters */); |
| 170 | } |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 171 | return resolveInfo; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 172 | } |
| 173 | |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 174 | public static void doInstantAppResolutionPhaseTwo(Context context, |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 175 | InstantAppResolverConnection connection, InstantAppRequest requestObj, |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 176 | ActivityInfo instantAppInstaller, Handler callbackHandler) { |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 177 | final long startTime = System.currentTimeMillis(); |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 178 | final String token = requestObj.responseObj.token; |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 179 | if (DEBUG_INSTANT) { |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 180 | Log.d(TAG, "[" + token + "] Phase2; resolving"); |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 181 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 182 | final Intent origIntent = requestObj.origIntent; |
| 183 | final Intent sanitizedIntent = sanitizeIntent(origIntent); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 184 | |
| 185 | final PhaseTwoCallback callback = new PhaseTwoCallback() { |
| 186 | @Override |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 187 | void onPhaseTwoResolved(List<InstantAppResolveInfo> instantAppResolveInfoList, |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 188 | long startTime) { |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 189 | final Intent failureIntent; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 190 | if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { |
| 191 | final AuxiliaryResolveInfo instantAppIntentInfo = |
| 192 | InstantAppResolver.filterInstantAppIntent( |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 193 | instantAppResolveInfoList, origIntent, null /*resolvedType*/, |
Patrick Baumann | 4db6bc1 | 2018-02-06 09:55:36 -0800 | [diff] [blame] | 194 | 0 /*userId*/, origIntent.getPackage(), requestObj.digest, |
| 195 | token); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 196 | if (instantAppIntentInfo != null) { |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 197 | failureIntent = instantAppIntentInfo.failureIntent; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 198 | } else { |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 199 | failureIntent = null; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 200 | } |
| 201 | } else { |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 202 | failureIntent = null; |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 203 | } |
| 204 | final Intent installerIntent = buildEphemeralInstallerIntent( |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 205 | requestObj.origIntent, |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 206 | sanitizedIntent, |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 207 | failureIntent, |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 208 | requestObj.callingPackage, |
Chad Brubaker | 0606861 | 2017-04-06 09:43:47 -0700 | [diff] [blame] | 209 | requestObj.verificationBundle, |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 210 | requestObj.resolvedType, |
| 211 | requestObj.userId, |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 212 | requestObj.responseObj.installFailureActivity, |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 213 | token, |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 214 | false /*needsPhaseTwo*/, |
| 215 | requestObj.responseObj.filters); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 216 | installerIntent.setComponent(new ComponentName( |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 217 | instantAppInstaller.packageName, instantAppInstaller.name)); |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 218 | |
| 219 | logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 220 | requestObj.responseObj.filters != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE); |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 221 | |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 222 | context.startActivity(installerIntent); |
| 223 | } |
| 224 | }; |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 225 | try { |
Patrick Baumann | 4db6bc1 | 2018-02-06 09:55:36 -0800 | [diff] [blame] | 226 | connection.getInstantAppIntentFilterList(sanitizedIntent, |
| 227 | requestObj.digest.getDigestPrefixSecure(), token, callback, callbackHandler, |
| 228 | startTime); |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 229 | } catch (ConnectionException e) { |
| 230 | @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; |
| 231 | if (e.failure == ConnectionException.FAILURE_BIND) { |
| 232 | resolutionStatus = RESOLUTION_BIND_TIMEOUT; |
| 233 | } |
| 234 | logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, |
| 235 | resolutionStatus); |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 236 | if (DEBUG_INSTANT) { |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 237 | if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { |
| 238 | Log.d(TAG, "[" + token + "] Phase2; bind timed out"); |
| 239 | } else { |
| 240 | Log.d(TAG, "[" + token + "] Phase2; service connection error"); |
| 241 | } |
| 242 | } |
| 243 | } |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 244 | } |
| 245 | |
| 246 | /** |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 247 | * Builds and returns an intent to launch the instant installer. |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 248 | */ |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 249 | public static Intent buildEphemeralInstallerIntent( |
| 250 | @NonNull Intent origIntent, |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 251 | @NonNull Intent sanitizedIntent, |
| 252 | @Nullable Intent failureIntent, |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 253 | @NonNull String callingPackage, |
Chad Brubaker | 0606861 | 2017-04-06 09:43:47 -0700 | [diff] [blame] | 254 | @Nullable Bundle verificationBundle, |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 255 | @NonNull String resolvedType, |
| 256 | int userId, |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 257 | @Nullable ComponentName installFailureActivity, |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 258 | @Nullable String token, |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 259 | boolean needsPhaseTwo, |
| 260 | List<AuxiliaryResolveInfo.AuxiliaryFilter> filters) { |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 261 | // Construct the intent that launches the instant installer |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 262 | int flags = origIntent.getFlags(); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 263 | final Intent intent = new Intent(); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 264 | intent.setFlags(flags |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 265 | | Intent.FLAG_ACTIVITY_NO_HISTORY |
| 266 | | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 267 | if (token != null) { |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 268 | // TODO(b/72700831): remove populating old extra |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 269 | intent.putExtra(Intent.EXTRA_EPHEMERAL_TOKEN, token); |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 270 | intent.putExtra(Intent.EXTRA_INSTANT_APP_TOKEN, token); |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 271 | } |
| 272 | if (origIntent.getData() != null) { |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 273 | // TODO(b/72700831): remove populating old extra |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 274 | intent.putExtra(Intent.EXTRA_EPHEMERAL_HOSTNAME, origIntent.getData().getHost()); |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 275 | intent.putExtra(Intent.EXTRA_INSTANT_APP_HOSTNAME, origIntent.getData().getHost()); |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 276 | } |
Patrick Baumann | b4165d7 | 2017-12-04 11:29:24 -0800 | [diff] [blame] | 277 | intent.putExtra(Intent.EXTRA_INSTANT_APP_ACTION, origIntent.getAction()); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 278 | intent.putExtra(Intent.EXTRA_INTENT, sanitizedIntent); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 279 | |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 280 | if (needsPhaseTwo) { |
| 281 | intent.setAction(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE); |
| 282 | } else { |
| 283 | // We have all of the data we need; just start the installer without a second phase |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 284 | if (failureIntent != null || installFailureActivity != null) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 285 | // Intent that is launched if the package couldn't be installed for any reason. |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 286 | try { |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 287 | final Intent onFailureIntent; |
| 288 | if (installFailureActivity != null) { |
| 289 | onFailureIntent = new Intent(); |
| 290 | onFailureIntent.setComponent(installFailureActivity); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 291 | if (filters != null && filters.size() == 1) { |
| 292 | onFailureIntent.putExtra(Intent.EXTRA_SPLIT_NAME, |
| 293 | filters.get(0).splitName); |
| 294 | } |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 295 | onFailureIntent.putExtra(Intent.EXTRA_INTENT, origIntent); |
| 296 | } else { |
| 297 | onFailureIntent = failureIntent; |
| 298 | } |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 299 | final IIntentSender failureIntentTarget = ActivityManager.getService() |
| 300 | .getIntentSender( |
| 301 | ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, |
| 302 | null /*token*/, null /*resultWho*/, 1 /*requestCode*/, |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 303 | new Intent[] { onFailureIntent }, |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 304 | new String[] { resolvedType }, |
Todd Kennedy | d0084f7 | 2017-07-28 13:56:14 -0700 | [diff] [blame] | 305 | PendingIntent.FLAG_CANCEL_CURRENT |
| 306 | | PendingIntent.FLAG_ONE_SHOT |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 307 | | PendingIntent.FLAG_IMMUTABLE, |
| 308 | null /*bOptions*/, userId); |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 309 | IntentSender failureSender = new IntentSender(failureIntentTarget); |
| 310 | // TODO(b/72700831): remove populating old extra |
| 311 | intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, failureSender); |
| 312 | intent.putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, failureSender); |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 313 | } catch (RemoteException ignore) { /* ignore; same process */ } |
| 314 | } |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 315 | |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 316 | // Intent that is launched if the package was installed successfully. |
| 317 | final Intent successIntent = new Intent(origIntent); |
Todd Kennedy | b3b43130 | 2017-03-20 16:05:48 -0700 | [diff] [blame] | 318 | successIntent.setLaunchToken(token); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 319 | try { |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 320 | final IIntentSender successIntentTarget = ActivityManager.getService() |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 321 | .getIntentSender( |
| 322 | ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, |
| 323 | null /*token*/, null /*resultWho*/, 0 /*requestCode*/, |
Todd Kennedy | e991022 | 2017-02-21 16:00:11 -0800 | [diff] [blame] | 324 | new Intent[] { successIntent }, |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 325 | new String[] { resolvedType }, |
| 326 | PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT |
| 327 | | PendingIntent.FLAG_IMMUTABLE, |
| 328 | null /*bOptions*/, userId); |
Patrick Baumann | 159cd02 | 2018-01-11 13:25:05 -0800 | [diff] [blame] | 329 | IntentSender successSender = new IntentSender(successIntentTarget); |
| 330 | // TODO(b/72700831): remove populating old extra |
| 331 | intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, successSender); |
| 332 | intent.putExtra(Intent.EXTRA_INSTANT_APP_SUCCESS, successSender); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 333 | } catch (RemoteException ignore) { /* ignore; same process */ } |
Chad Brubaker | 0606861 | 2017-04-06 09:43:47 -0700 | [diff] [blame] | 334 | if (verificationBundle != null) { |
| 335 | intent.putExtra(Intent.EXTRA_VERIFICATION_BUNDLE, verificationBundle); |
| 336 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 337 | intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage); |
Patrick Baumann | 860b8ba | 2018-01-31 01:33:50 +0000 | [diff] [blame] | 338 | |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 339 | if (filters != null) { |
| 340 | Bundle resolvableFilters[] = new Bundle[filters.size()]; |
| 341 | for (int i = 0, max = filters.size(); i < max; i++) { |
| 342 | Bundle resolvableFilter = new Bundle(); |
| 343 | AuxiliaryResolveInfo.AuxiliaryFilter filter = filters.get(i); |
| 344 | resolvableFilter.putBoolean(Intent.EXTRA_UNKNOWN_INSTANT_APP, |
| 345 | filter.resolveInfo != null |
| 346 | && filter.resolveInfo.shouldLetInstallerDecide()); |
| 347 | resolvableFilter.putString(Intent.EXTRA_PACKAGE_NAME, filter.packageName); |
| 348 | resolvableFilter.putString(Intent.EXTRA_SPLIT_NAME, filter.splitName); |
| 349 | resolvableFilter.putLong(Intent.EXTRA_LONG_VERSION_CODE, filter.versionCode); |
| 350 | resolvableFilter.putBundle(Intent.EXTRA_INSTANT_APP_EXTRAS, filter.extras); |
| 351 | resolvableFilters[i] = resolvableFilter; |
| 352 | if (i == 0) { |
| 353 | // for backwards compat, always set the first result on the intent and add |
| 354 | // the int version code |
| 355 | intent.putExtras(resolvableFilter); |
| 356 | intent.putExtra(Intent.EXTRA_VERSION_CODE, (int) filter.versionCode); |
| 357 | } |
| 358 | } |
| 359 | intent.putExtra(Intent.EXTRA_INSTANT_APP_BUNDLES, resolvableFilters); |
| 360 | } |
| 361 | intent.setAction(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE); |
| 362 | } |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 363 | return intent; |
| 364 | } |
| 365 | |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 366 | private static AuxiliaryResolveInfo filterInstantAppIntent( |
| 367 | List<InstantAppResolveInfo> instantAppResolveInfoList, |
Todd Kennedy | 7dd99e3 | 2017-05-03 16:12:49 -0700 | [diff] [blame] | 368 | Intent origIntent, String resolvedType, int userId, String packageName, |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 369 | InstantAppDigest digest, String token) { |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 370 | final int[] shaPrefix = digest.getDigestPrefix(); |
| 371 | final byte[][] digestBytes = digest.getDigestBytes(); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 372 | boolean requiresSecondPhase = false; |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 373 | ArrayList<AuxiliaryResolveInfo.AuxiliaryFilter> filters = null; |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 374 | boolean requiresPrefixMatch = origIntent.isWebIntent() || (shaPrefix.length > 0 |
| 375 | && (origIntent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) == 0); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 376 | for (InstantAppResolveInfo instantAppResolveInfo : instantAppResolveInfoList) { |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 377 | if (requiresPrefixMatch && instantAppResolveInfo.shouldLetInstallerDecide()) { |
| 378 | Slog.d(TAG, "InstantAppResolveInfo with mShouldLetInstallerDecide=true when digest" |
| 379 | + " required; ignoring"); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 380 | continue; |
| 381 | } |
| 382 | byte[] filterDigestBytes = instantAppResolveInfo.getDigestBytes(); |
| 383 | // Only include matching digests if we have a prefix and we're either dealing with a |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 384 | // prefixed request or the resolveInfo specifies digest details. |
| 385 | if (shaPrefix.length > 0 && (requiresPrefixMatch || filterDigestBytes.length > 0)) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 386 | boolean matchFound = false; |
| 387 | // Go in reverse order so we match the narrowest scope first. |
| 388 | for (int i = shaPrefix.length - 1; i >= 0; --i) { |
| 389 | if (Arrays.equals(digestBytes[i], filterDigestBytes)) { |
| 390 | matchFound = true; |
| 391 | break; |
| 392 | } |
| 393 | } |
| 394 | if (!matchFound) { |
Patrick Baumann | 860b8ba | 2018-01-31 01:33:50 +0000 | [diff] [blame] | 395 | continue; |
| 396 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 397 | } |
| 398 | // We matched a resolve info; resolve the filters to see if anything matches completely. |
| 399 | List<AuxiliaryResolveInfo.AuxiliaryFilter> matchFilters = computeResolveFilters( |
| 400 | origIntent, resolvedType, userId, packageName, token, instantAppResolveInfo); |
| 401 | if (matchFilters != null) { |
| 402 | if (matchFilters.isEmpty()) { |
| 403 | requiresSecondPhase = true; |
Patrick Baumann | 860b8ba | 2018-01-31 01:33:50 +0000 | [diff] [blame] | 404 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 405 | if (filters == null) { |
| 406 | filters = new ArrayList<>(matchFilters); |
| 407 | } else { |
| 408 | filters.addAll(matchFilters); |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 409 | } |
Patrick Baumann | 3e8bd0f | 2018-01-08 11:23:38 -0800 | [diff] [blame] | 410 | } |
Patrick Baumann | 3e8bd0f | 2018-01-08 11:23:38 -0800 | [diff] [blame] | 411 | } |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 412 | if (filters != null && !filters.isEmpty()) { |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 413 | return new AuxiliaryResolveInfo(token, requiresSecondPhase, |
| 414 | createFailureIntent(origIntent, token), filters); |
Patrick Baumann | 3e0b8ee | 2018-04-26 12:03:15 -0700 | [diff] [blame] | 415 | } |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 416 | // Hash or filter mis-match; no instant apps for this domain. |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 417 | return null; |
| 418 | } |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 419 | |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 420 | /** |
Patrick Baumann | a6862c2 | 2018-05-03 13:16:01 -0700 | [diff] [blame] | 421 | * Creates a failure intent for the installer to send in the case that the instant app cannot be |
| 422 | * launched for any reason. |
| 423 | */ |
| 424 | private static Intent createFailureIntent(Intent origIntent, String token) { |
| 425 | final Intent failureIntent = new Intent(origIntent); |
| 426 | failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL); |
| 427 | failureIntent.setFlags(failureIntent.getFlags() & ~Intent.FLAG_ACTIVITY_MATCH_EXTERNAL); |
| 428 | failureIntent.setLaunchToken(token); |
| 429 | return failureIntent; |
| 430 | } |
| 431 | |
| 432 | /** |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 433 | * Returns one of three states: <p/> |
| 434 | * <ul> |
| 435 | * <li>{@code null} if there are no matches will not be; resolution is unnecessary.</li> |
| 436 | * <li>An empty list signifying that a 2nd phase of resolution is required.</li> |
| 437 | * <li>A populated list meaning that matches were found and should be sent directly to the |
| 438 | * installer</li> |
| 439 | * </ul> |
| 440 | * |
| 441 | */ |
| 442 | private static List<AuxiliaryResolveInfo.AuxiliaryFilter> computeResolveFilters( |
| 443 | Intent origIntent, String resolvedType, int userId, String packageName, String token, |
| 444 | InstantAppResolveInfo instantAppInfo) { |
| 445 | if (instantAppInfo.shouldLetInstallerDecide()) { |
| 446 | return Collections.singletonList( |
| 447 | new AuxiliaryResolveInfo.AuxiliaryFilter( |
| 448 | instantAppInfo, null /* splitName */, |
| 449 | instantAppInfo.getExtras())); |
| 450 | } |
| 451 | if (packageName != null |
| 452 | && !packageName.equals(instantAppInfo.getPackageName())) { |
| 453 | return null; |
| 454 | } |
| 455 | final List<InstantAppIntentFilter> instantAppFilters = |
| 456 | instantAppInfo.getIntentFilters(); |
| 457 | if (instantAppFilters == null || instantAppFilters.isEmpty()) { |
| 458 | // No filters on web intent; no matches, 2nd phase unnecessary. |
Patrick Baumann | 0da8537 | 2018-02-02 16:07:35 -0800 | [diff] [blame] | 459 | if (origIntent.isWebIntent()) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 460 | return null; |
| 461 | } |
| 462 | // No filters; we need to start phase two |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 463 | if (DEBUG_INSTANT) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 464 | Log.d(TAG, "No app filters; go to phase 2"); |
| 465 | } |
| 466 | return Collections.emptyList(); |
| 467 | } |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 468 | final PackageManagerService.InstantAppIntentResolver instantAppResolver = |
| 469 | new PackageManagerService.InstantAppIntentResolver(); |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 470 | for (int j = instantAppFilters.size() - 1; j >= 0; --j) { |
| 471 | final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j); |
| 472 | final List<IntentFilter> splitFilters = instantAppFilter.getFilters(); |
| 473 | if (splitFilters == null || splitFilters.isEmpty()) { |
| 474 | continue; |
| 475 | } |
| 476 | for (int k = splitFilters.size() - 1; k >= 0; --k) { |
| 477 | IntentFilter filter = splitFilters.get(k); |
| 478 | Iterator<IntentFilter.AuthorityEntry> authorities = |
| 479 | filter.authoritiesIterator(); |
| 480 | // ignore http/s-only filters. |
| 481 | if ((authorities == null || !authorities.hasNext()) |
| 482 | && (filter.hasDataScheme("http") || filter.hasDataScheme("https")) |
| 483 | && filter.hasAction(Intent.ACTION_VIEW) |
| 484 | && filter.hasCategory(Intent.CATEGORY_BROWSABLE)) { |
| 485 | continue; |
| 486 | } |
| 487 | instantAppResolver.addFilter( |
| 488 | new AuxiliaryResolveInfo.AuxiliaryFilter( |
| 489 | filter, |
| 490 | instantAppInfo, |
| 491 | instantAppFilter.getSplitName(), |
| 492 | instantAppInfo.getExtras() |
| 493 | )); |
| 494 | } |
| 495 | } |
| 496 | List<AuxiliaryResolveInfo.AuxiliaryFilter> matchedResolveInfoList = |
| 497 | instantAppResolver.queryIntent( |
| 498 | origIntent, resolvedType, false /*defaultOnly*/, userId); |
| 499 | if (!matchedResolveInfoList.isEmpty()) { |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 500 | if (DEBUG_INSTANT) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 501 | Log.d(TAG, "[" + token + "] Found match(es); " + matchedResolveInfoList); |
| 502 | } |
| 503 | return matchedResolveInfoList; |
Patrick Baumann | 43c97a0 | 2018-01-31 20:09:03 +0000 | [diff] [blame] | 504 | } else if (DEBUG_INSTANT) { |
Patrick Baumann | 577d402 | 2018-01-31 16:55:10 +0000 | [diff] [blame] | 505 | Log.d(TAG, "[" + token + "] No matches found" |
| 506 | + " package: " + instantAppInfo.getPackageName() |
| 507 | + ", versionCode: " + instantAppInfo.getVersionCode()); |
| 508 | } |
| 509 | return null; |
| 510 | } |
| 511 | |
Todd Kennedy | bdf2a80 | 2017-05-08 16:09:42 -0700 | [diff] [blame] | 512 | private static void logMetrics(int action, long startTime, String token, |
| 513 | @ResolutionStatus int status) { |
Todd Kennedy | 50d946c1 | 2017-03-17 13:55:38 -0700 | [diff] [blame] | 514 | final LogMaker logMaker = new LogMaker(action) |
| 515 | .setType(MetricsProto.MetricsEvent.TYPE_ACTION) |
| 516 | .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_DELAY_MS, |
| 517 | new Long(System.currentTimeMillis() - startTime)) |
| 518 | .addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, token) |
| 519 | .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_STATUS, new Integer(status)); |
| 520 | getLogger().write(logMaker); |
| 521 | } |
Todd Kennedy | 01ad0c7 | 2016-11-11 15:33:12 -0800 | [diff] [blame] | 522 | } |