Loading services/core/java/com/android/server/pm/EphemeralResolverConnection.java +38 −19 Original line number Diff line number Diff line Loading @@ -80,19 +80,23 @@ final class EphemeralResolverConnection implements DeathRecipient { } public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[], String token) { String token) throws ConnectionException { throwIfCalledOnMainThread(); IInstantAppResolver target = null; try { try { target = getRemoteInstanceLazy(token); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (InterruptedException e) { throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED); } try { return mGetEphemeralResolveInfoCaller .getEphemeralResolveInfoList(target, hashPrefix, token); } catch (RemoteException e) { } catch (InterruptedException | TimeoutException e) { if (target == null) { Slog.w(TAG, "[" + token + "] Timeout! Phase1 binding to instant app resolver"); } else { Slog.w(TAG, "[" + token + "] Timeout! Phase1 resolving instant app"); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (RemoteException ignore) { } } finally { synchronized (mLock) { Loading @@ -104,7 +108,7 @@ final class EphemeralResolverConnection implements DeathRecipient { public final void getInstantAppIntentFilterList(int hashPrefix[], String token, String hostName, PhaseTwoCallback callback, Handler callbackHandler, final long startTime) { final long startTime) throws ConnectionException { final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() { @Override public void sendResult(Bundle data) throws RemoteException { Loading @@ -122,14 +126,16 @@ final class EphemeralResolverConnection implements DeathRecipient { try { getRemoteInstanceLazy(token) .getInstantAppIntentFilterList(hashPrefix, token, hostName, remoteCallback); } catch (RemoteException e) { } catch (InterruptedException | TimeoutException e) { Slog.w(TAG, "[" + token + "] Timeout! Phase2 binding to instant app resolver"); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (InterruptedException e) { throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED); } catch (RemoteException ignore) { } } private IInstantAppResolver getRemoteInstanceLazy(String token) throws TimeoutException, InterruptedException { throws ConnectionException, TimeoutException, InterruptedException { synchronized (mLock) { if (mRemoteInstance != null) { return mRemoteInstance; Loading @@ -139,7 +145,7 @@ final class EphemeralResolverConnection implements DeathRecipient { } } private void waitForBind(String token) throws TimeoutException, InterruptedException { private void waitForBindLocked(String token) throws TimeoutException, InterruptedException { final long startMillis = SystemClock.uptimeMillis(); while (mIsBinding) { if (mRemoteInstance != null) { Loading @@ -154,12 +160,13 @@ final class EphemeralResolverConnection implements DeathRecipient { } } private void bindLocked(String token) throws TimeoutException, InterruptedException { private void bindLocked(String token) throws ConnectionException, TimeoutException, InterruptedException { if (DEBUG_EPHEMERAL && mIsBinding && mRemoteInstance == null) { Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection"); } try { waitForBind(token); waitForBindLocked(token); } catch (TimeoutException e) { if (DEBUG_EPHEMERAL) { Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding"); Loading @@ -179,9 +186,10 @@ final class EphemeralResolverConnection implements DeathRecipient { wasBound = mContext .bindServiceAsUser(mIntent, mServiceConnection, flags, UserHandle.SYSTEM); if (wasBound) { waitForBind(token); waitForBindLocked(token); } else { Slog.w(TAG, "[" + token + "] Failed to bind to: " + mIntent); throw new ConnectionException(ConnectionException.FAILURE_BIND); } } finally { mIsBinding = wasBound && mRemoteInstance == null; Loading Loading @@ -222,6 +230,17 @@ final class EphemeralResolverConnection implements DeathRecipient { List<InstantAppResolveInfo> instantAppResolveInfoList, long startTime); } public static class ConnectionException extends Exception { public static final int FAILURE_BIND = 1; public static final int FAILURE_CALL = 2; public static final int FAILURE_INTERRUPTED = 3; public final int failure; public ConnectionException(int _failure) { failure = _failure; } } private final class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { Loading services/core/java/com/android/server/pm/InstantAppResolver.java +69 −20 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_STATUS; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -50,20 +51,37 @@ import android.util.Slog; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.server.pm.EphemeralResolverConnection.ConnectionException; import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeoutException; /** @hide */ public abstract class InstantAppResolver { private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; private static final String TAG = "PackageManager"; private static int RESOLUTION_SUCCESS = 0; private static int RESOLUTION_FAILURE = 1; private static final int RESOLUTION_SUCCESS = 0; private static final int RESOLUTION_FAILURE = 1; /** Binding to the external service timed out */ private static final int RESOLUTION_BIND_TIMEOUT = 2; /** The call to retrieve an instant application response timed out */ private static final int RESOLUTION_CALL_TIMEOUT = 3; @IntDef(flag = true, prefix = { "RESOLUTION_" }, value = { RESOLUTION_SUCCESS, RESOLUTION_FAILURE, RESOLUTION_BIND_TIMEOUT, RESOLUTION_CALL_TIMEOUT, }) @Retention(RetentionPolicy.SOURCE) public @interface ResolutionStatus {} private static MetricsLogger sMetricsLogger; private static MetricsLogger getLogger() { Loading @@ -78,29 +96,43 @@ public abstract class InstantAppResolver { final long startTime = System.currentTimeMillis(); final String token = UUID.randomUUID().toString(); if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Resolving phase 1"); Log.d(TAG, "[" + token + "] Phase1; resolving"); } final Intent intent = requestObj.origIntent; final InstantAppDigest digest = new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/); final int[] shaPrefix = digest.getDigestPrefix(); AuxiliaryResolveInfo resolveInfo = null; @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS; try { final List<InstantAppResolveInfo> instantAppResolveInfoList = connection.getInstantAppResolveInfoList(shaPrefix, token); if (instantAppResolveInfoList == null || instantAppResolveInfoList.size() == 0) { // No hash prefix match; there are no instant apps for this domain. if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] No results returned"); if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, intent, requestObj.resolvedType, requestObj.userId, intent.getPackage(), digest, token); } } catch (ConnectionException e) { if (e.failure == ConnectionException.FAILURE_BIND) { resolutionStatus = RESOLUTION_BIND_TIMEOUT; } else if (e.failure == ConnectionException.FAILURE_CALL) { resolutionStatus = RESOLUTION_CALL_TIMEOUT; } else { resolutionStatus = RESOLUTION_FAILURE; } return null; } final AuxiliaryResolveInfo resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, intent, requestObj.resolvedType, requestObj.userId, intent.getPackage(), digest, token); logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, RESOLUTION_SUCCESS); resolutionStatus); if (DEBUG_EPHEMERAL && resolveInfo == null) { Log.d(TAG, "[" + token + "] No results matched"); if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase1; bind timed out"); } else if (resolutionStatus == RESOLUTION_CALL_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase1; call timed out"); } else if (resolutionStatus != RESOLUTION_SUCCESS) { Log.d(TAG, "[" + token + "] Phase1; service connection error"); } else { Log.d(TAG, "[" + token + "] Phase1; No results matched"); } } return resolveInfo; } Loading @@ -111,7 +143,7 @@ public abstract class InstantAppResolver { final long startTime = System.currentTimeMillis(); final String token = requestObj.responseObj.token; if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Resolving phase 2"); Log.d(TAG, "[" + token + "] Phase2; resolving"); } final Intent intent = requestObj.origIntent; final String hostName = intent.getData().getHost(); Loading Loading @@ -170,8 +202,24 @@ public abstract class InstantAppResolver { context.startActivity(installerIntent); } }; try { connection.getInstantAppIntentFilterList( shaPrefix, token, hostName, callback, callbackHandler, startTime); } catch (ConnectionException e) { @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; if (e.failure == ConnectionException.FAILURE_BIND) { resolutionStatus = RESOLUTION_BIND_TIMEOUT; } logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, resolutionStatus); if (DEBUG_EPHEMERAL) { if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase2; bind timed out"); } else { Log.d(TAG, "[" + token + "] Phase2; service connection error"); } } } } /** Loading Loading @@ -322,7 +370,8 @@ public abstract class InstantAppResolver { return null; } private static void logMetrics(int action, long startTime, String token, int status) { private static void logMetrics(int action, long startTime, String token, @ResolutionStatus int status) { final LogMaker logMaker = new LogMaker(action) .setType(MetricsProto.MetricsEvent.TYPE_ACTION) .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_DELAY_MS, Loading Loading
services/core/java/com/android/server/pm/EphemeralResolverConnection.java +38 −19 Original line number Diff line number Diff line Loading @@ -80,19 +80,23 @@ final class EphemeralResolverConnection implements DeathRecipient { } public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[], String token) { String token) throws ConnectionException { throwIfCalledOnMainThread(); IInstantAppResolver target = null; try { try { target = getRemoteInstanceLazy(token); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (InterruptedException e) { throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED); } try { return mGetEphemeralResolveInfoCaller .getEphemeralResolveInfoList(target, hashPrefix, token); } catch (RemoteException e) { } catch (InterruptedException | TimeoutException e) { if (target == null) { Slog.w(TAG, "[" + token + "] Timeout! Phase1 binding to instant app resolver"); } else { Slog.w(TAG, "[" + token + "] Timeout! Phase1 resolving instant app"); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (RemoteException ignore) { } } finally { synchronized (mLock) { Loading @@ -104,7 +108,7 @@ final class EphemeralResolverConnection implements DeathRecipient { public final void getInstantAppIntentFilterList(int hashPrefix[], String token, String hostName, PhaseTwoCallback callback, Handler callbackHandler, final long startTime) { final long startTime) throws ConnectionException { final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() { @Override public void sendResult(Bundle data) throws RemoteException { Loading @@ -122,14 +126,16 @@ final class EphemeralResolverConnection implements DeathRecipient { try { getRemoteInstanceLazy(token) .getInstantAppIntentFilterList(hashPrefix, token, hostName, remoteCallback); } catch (RemoteException e) { } catch (InterruptedException | TimeoutException e) { Slog.w(TAG, "[" + token + "] Timeout! Phase2 binding to instant app resolver"); } catch (TimeoutException e) { throw new ConnectionException(ConnectionException.FAILURE_BIND); } catch (InterruptedException e) { throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED); } catch (RemoteException ignore) { } } private IInstantAppResolver getRemoteInstanceLazy(String token) throws TimeoutException, InterruptedException { throws ConnectionException, TimeoutException, InterruptedException { synchronized (mLock) { if (mRemoteInstance != null) { return mRemoteInstance; Loading @@ -139,7 +145,7 @@ final class EphemeralResolverConnection implements DeathRecipient { } } private void waitForBind(String token) throws TimeoutException, InterruptedException { private void waitForBindLocked(String token) throws TimeoutException, InterruptedException { final long startMillis = SystemClock.uptimeMillis(); while (mIsBinding) { if (mRemoteInstance != null) { Loading @@ -154,12 +160,13 @@ final class EphemeralResolverConnection implements DeathRecipient { } } private void bindLocked(String token) throws TimeoutException, InterruptedException { private void bindLocked(String token) throws ConnectionException, TimeoutException, InterruptedException { if (DEBUG_EPHEMERAL && mIsBinding && mRemoteInstance == null) { Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection"); } try { waitForBind(token); waitForBindLocked(token); } catch (TimeoutException e) { if (DEBUG_EPHEMERAL) { Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding"); Loading @@ -179,9 +186,10 @@ final class EphemeralResolverConnection implements DeathRecipient { wasBound = mContext .bindServiceAsUser(mIntent, mServiceConnection, flags, UserHandle.SYSTEM); if (wasBound) { waitForBind(token); waitForBindLocked(token); } else { Slog.w(TAG, "[" + token + "] Failed to bind to: " + mIntent); throw new ConnectionException(ConnectionException.FAILURE_BIND); } } finally { mIsBinding = wasBound && mRemoteInstance == null; Loading Loading @@ -222,6 +230,17 @@ final class EphemeralResolverConnection implements DeathRecipient { List<InstantAppResolveInfo> instantAppResolveInfoList, long startTime); } public static class ConnectionException extends Exception { public static final int FAILURE_BIND = 1; public static final int FAILURE_CALL = 2; public static final int FAILURE_INTERRUPTED = 3; public final int failure; public ConnectionException(int _failure) { failure = _failure; } } private final class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { Loading
services/core/java/com/android/server/pm/InstantAppResolver.java +69 −20 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_STATUS; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading Loading @@ -50,20 +51,37 @@ import android.util.Slog; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.server.pm.EphemeralResolverConnection.ConnectionException; import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeoutException; /** @hide */ public abstract class InstantAppResolver { private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; private static final String TAG = "PackageManager"; private static int RESOLUTION_SUCCESS = 0; private static int RESOLUTION_FAILURE = 1; private static final int RESOLUTION_SUCCESS = 0; private static final int RESOLUTION_FAILURE = 1; /** Binding to the external service timed out */ private static final int RESOLUTION_BIND_TIMEOUT = 2; /** The call to retrieve an instant application response timed out */ private static final int RESOLUTION_CALL_TIMEOUT = 3; @IntDef(flag = true, prefix = { "RESOLUTION_" }, value = { RESOLUTION_SUCCESS, RESOLUTION_FAILURE, RESOLUTION_BIND_TIMEOUT, RESOLUTION_CALL_TIMEOUT, }) @Retention(RetentionPolicy.SOURCE) public @interface ResolutionStatus {} private static MetricsLogger sMetricsLogger; private static MetricsLogger getLogger() { Loading @@ -78,29 +96,43 @@ public abstract class InstantAppResolver { final long startTime = System.currentTimeMillis(); final String token = UUID.randomUUID().toString(); if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Resolving phase 1"); Log.d(TAG, "[" + token + "] Phase1; resolving"); } final Intent intent = requestObj.origIntent; final InstantAppDigest digest = new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/); final int[] shaPrefix = digest.getDigestPrefix(); AuxiliaryResolveInfo resolveInfo = null; @ResolutionStatus int resolutionStatus = RESOLUTION_SUCCESS; try { final List<InstantAppResolveInfo> instantAppResolveInfoList = connection.getInstantAppResolveInfoList(shaPrefix, token); if (instantAppResolveInfoList == null || instantAppResolveInfoList.size() == 0) { // No hash prefix match; there are no instant apps for this domain. if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] No results returned"); if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, intent, requestObj.resolvedType, requestObj.userId, intent.getPackage(), digest, token); } } catch (ConnectionException e) { if (e.failure == ConnectionException.FAILURE_BIND) { resolutionStatus = RESOLUTION_BIND_TIMEOUT; } else if (e.failure == ConnectionException.FAILURE_CALL) { resolutionStatus = RESOLUTION_CALL_TIMEOUT; } else { resolutionStatus = RESOLUTION_FAILURE; } return null; } final AuxiliaryResolveInfo resolveInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, intent, requestObj.resolvedType, requestObj.userId, intent.getPackage(), digest, token); logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, RESOLUTION_SUCCESS); resolutionStatus); if (DEBUG_EPHEMERAL && resolveInfo == null) { Log.d(TAG, "[" + token + "] No results matched"); if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase1; bind timed out"); } else if (resolutionStatus == RESOLUTION_CALL_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase1; call timed out"); } else if (resolutionStatus != RESOLUTION_SUCCESS) { Log.d(TAG, "[" + token + "] Phase1; service connection error"); } else { Log.d(TAG, "[" + token + "] Phase1; No results matched"); } } return resolveInfo; } Loading @@ -111,7 +143,7 @@ public abstract class InstantAppResolver { final long startTime = System.currentTimeMillis(); final String token = requestObj.responseObj.token; if (DEBUG_EPHEMERAL) { Log.d(TAG, "[" + token + "] Resolving phase 2"); Log.d(TAG, "[" + token + "] Phase2; resolving"); } final Intent intent = requestObj.origIntent; final String hostName = intent.getData().getHost(); Loading Loading @@ -170,8 +202,24 @@ public abstract class InstantAppResolver { context.startActivity(installerIntent); } }; try { connection.getInstantAppIntentFilterList( shaPrefix, token, hostName, callback, callbackHandler, startTime); } catch (ConnectionException e) { @ResolutionStatus int resolutionStatus = RESOLUTION_FAILURE; if (e.failure == ConnectionException.FAILURE_BIND) { resolutionStatus = RESOLUTION_BIND_TIMEOUT; } logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, resolutionStatus); if (DEBUG_EPHEMERAL) { if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) { Log.d(TAG, "[" + token + "] Phase2; bind timed out"); } else { Log.d(TAG, "[" + token + "] Phase2; service connection error"); } } } } /** Loading Loading @@ -322,7 +370,8 @@ public abstract class InstantAppResolver { return null; } private static void logMetrics(int action, long startTime, String token, int status) { private static void logMetrics(int action, long startTime, String token, @ResolutionStatus int status) { final LogMaker logMaker = new LogMaker(action) .setType(MetricsProto.MetricsEvent.TYPE_ACTION) .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_DELAY_MS, Loading