Revert "Removes EphemrealResolverService and related"
This reverts commit 5564f880db3292327872a07df8e230eee78be14b.
Reason for revert: Resolve merge conflict for another revert (ag/3537193)
Bug: 72710855
Change-Id: Id7c3a3993a45c588ee4668d7486d67d764541b1e
(cherry picked from commit 1e0c91968e802d49c26e2e8d6ca6e8d31f451894)
diff --git a/api/current.txt b/api/current.txt
index f5da9b05..7f07f81 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11613,15 +11613,15 @@
public final class AssetManager implements java.lang.AutoCloseable {
method public void close();
- method public final java.lang.String[] getLocales();
- method public final java.lang.String[] list(java.lang.String) throws java.io.IOException;
- method public final java.io.InputStream open(java.lang.String) throws java.io.IOException;
- method public final java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
- method public final android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
- method public final android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
+ method public java.lang.String[] getLocales();
+ method public java.lang.String[] list(java.lang.String) throws java.io.IOException;
+ method public java.io.InputStream open(java.lang.String) throws java.io.IOException;
+ method public java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
+ method public android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
+ method public android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
field public static final int ACCESS_BUFFER = 3; // 0x3
field public static final int ACCESS_RANDOM = 1; // 0x1
field public static final int ACCESS_STREAMING = 2; // 0x2
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 48f43e0..b63703d 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -1,5 +1,13 @@
package android.app {
+ public abstract deprecated class EphemeralResolverService extends android.app.InstantAppResolverService {
+ ctor public EphemeralResolverService();
+ method public android.os.Looper getLooper();
+ method public abstract deprecated java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
+ method public android.content.pm.EphemeralResolveInfo onGetEphemeralIntentFilter(java.lang.String);
+ method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralResolveInfo(int[]);
+ }
+
public class Notification implements android.os.Parcelable {
method public static java.lang.Class<? extends android.app.Notification.Style> getNotificationStyleClass(java.lang.String);
}
@@ -23,7 +31,10 @@
public class Intent implements java.lang.Cloneable android.os.Parcelable {
field public static final deprecated java.lang.String ACTION_DEVICE_INITIALIZATION_WIZARD = "android.intent.action.DEVICE_INITIALIZATION_WIZARD";
+ field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
+ field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
@@ -51,6 +62,45 @@
}
+package android.content.pm {
+
+ public final deprecated class EphemeralIntentFilter implements android.os.Parcelable {
+ ctor public EphemeralIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
+ method public int describeContents();
+ method public java.util.List<android.content.IntentFilter> getFilters();
+ method public java.lang.String getSplitName();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralIntentFilter> CREATOR;
+ }
+
+ public final deprecated class EphemeralResolveInfo implements android.os.Parcelable {
+ ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
+ ctor public deprecated EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
+ ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>, int);
+ ctor public EphemeralResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
+ method public int describeContents();
+ method public byte[] getDigestBytes();
+ method public int getDigestPrefix();
+ method public deprecated java.util.List<android.content.IntentFilter> getFilters();
+ method public java.util.List<android.content.pm.EphemeralIntentFilter> getIntentFilters();
+ method public java.lang.String getPackageName();
+ method public int getVersionCode();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo> CREATOR;
+ field public static final java.lang.String SHA_ALGORITHM = "SHA-256";
+ }
+
+ public static final class EphemeralResolveInfo.EphemeralDigest implements android.os.Parcelable {
+ ctor public EphemeralResolveInfo.EphemeralDigest(java.lang.String);
+ method public int describeContents();
+ method public byte[][] getDigestBytes();
+ method public int[] getDigestPrefix();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo.EphemeralDigest> CREATOR;
+ }
+
+}
+
package android.media.tv {
public final class TvInputManager {
diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java
new file mode 100644
index 0000000..d1c2441
--- /dev/null
+++ b/core/java/android/app/EphemeralResolverService.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 android.app;
+
+import android.annotation.SystemApi;
+import android.content.pm.EphemeralResolveInfo;
+import android.content.pm.InstantAppResolveInfo;
+import android.os.Build;
+import android.os.Looper;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Base class for implementing the resolver service.
+ * @hide
+ * @removed
+ * @deprecated use InstantAppResolverService instead
+ */
+@Deprecated
+@SystemApi
+public abstract class EphemeralResolverService extends InstantAppResolverService {
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
+ private static final String TAG = "PackageManager";
+
+ /**
+ * Called to retrieve resolve info for ephemeral applications.
+ *
+ * @param digestPrefix The hash prefix of the ephemeral's domain.
+ * @param prefixMask A mask that was applied to each digest prefix. This should
+ * be used when comparing against the digest prefixes as all bits might
+ * not be set.
+ * @deprecated use {@link #onGetEphemeralResolveInfo(int[])} instead
+ */
+ @Deprecated
+ public abstract List<EphemeralResolveInfo> onEphemeralResolveInfoList(
+ int digestPrefix[], int prefix);
+
+ /**
+ * Called to retrieve resolve info for ephemeral applications.
+ *
+ * @param digestPrefix The hash prefix of the ephemeral's domain.
+ */
+ public List<EphemeralResolveInfo> onGetEphemeralResolveInfo(int digestPrefix[]) {
+ return onEphemeralResolveInfoList(digestPrefix, 0xFFFFF000);
+ }
+
+ /**
+ * Called to retrieve intent filters for ephemeral applications.
+ *
+ * @param hostName The name of the host to get intent filters for.
+ */
+ public EphemeralResolveInfo onGetEphemeralIntentFilter(String hostName) {
+ throw new IllegalStateException("Must define");
+ }
+
+ @Override
+ public Looper getLooper() {
+ return super.getLooper();
+ }
+
+ void _onGetInstantAppResolveInfo(int[] digestPrefix, String token,
+ InstantAppResolutionCallback callback) {
+ if (DEBUG_EPHEMERAL) {
+ Log.d(TAG, "Legacy resolver; getInstantAppResolveInfo;"
+ + " prefix: " + Arrays.toString(digestPrefix));
+ }
+ final List<EphemeralResolveInfo> response = onGetEphemeralResolveInfo(digestPrefix);
+ final int responseSize = response == null ? 0 : response.size();
+ final List<InstantAppResolveInfo> resultList = new ArrayList<>(responseSize);
+ for (int i = 0; i < responseSize; i++) {
+ resultList.add(response.get(i).getInstantAppResolveInfo());
+ }
+ callback.onInstantAppResolveInfo(resultList);
+ }
+
+ void _onGetInstantAppIntentFilter(int[] digestPrefix, String token,
+ String hostName, InstantAppResolutionCallback callback) {
+ if (DEBUG_EPHEMERAL) {
+ Log.d(TAG, "Legacy resolver; getInstantAppIntentFilter;"
+ + " prefix: " + Arrays.toString(digestPrefix));
+ }
+ final EphemeralResolveInfo response = onGetEphemeralIntentFilter(hostName);
+ final List<InstantAppResolveInfo> resultList = new ArrayList<>(1);
+ resultList.add(response.getInstantAppResolveInfo());
+ callback.onInstantAppResolveInfo(resultList);
+ }
+}
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
index 76a3682..89aff36 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -43,7 +43,7 @@
*/
@SystemApi
public abstract class InstantAppResolverService extends Service {
- private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
private static final String TAG = "PackageManager";
/** @hide */
@@ -133,7 +133,7 @@
@Override
public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix,
String token, int sequence, IRemoteCallback callback) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "[" + token + "] Phase1 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
@@ -148,7 +148,7 @@
@Override
public void getInstantAppIntentFilterList(Intent sanitizedIntent,
int[] digestPrefix, String token, IRemoteCallback callback) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "[" + token + "] Phase2 called; posting");
}
final SomeArgs args = SomeArgs.obtain();
@@ -203,7 +203,7 @@
final String token = (String) args.arg3;
final Intent intent = (Intent) args.arg4;
final int sequence = message.arg1;
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "[" + token + "] Phase1 request;"
+ " prefix: " + Arrays.toString(digestPrefix));
}
@@ -217,7 +217,7 @@
final int[] digestPrefix = (int[]) args.arg2;
final String token = (String) args.arg3;
final Intent intent = (Intent) args.arg4;
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "[" + token + "] Phase2 request;"
+ " prefix: " + Arrays.toString(digestPrefix));
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 908465e..b3c8737 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1554,6 +1554,16 @@
public static final String ACTION_INSTALL_FAILURE = "android.intent.action.INSTALL_FAILURE";
/**
+ * @hide
+ * @removed
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
+ = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+ /**
* Activity Action: Launch instant application installer.
* <p class="note">
* This is a protected intent that can only be sent by the system.
@@ -1567,6 +1577,16 @@
= "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
/**
+ * @hide
+ * @removed
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
+ = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+ /**
* Service Action: Resolve instant application.
* <p>
* The system will have a persistent connection to this service.
@@ -1581,6 +1601,16 @@
= "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
/**
+ * @hide
+ * @removed
+ * @deprecated Do not use. This will go away.
+ * Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}.
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
+ = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+ /**
* Activity Action: Launch instant app settings.
*
* <p class="note">
diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java
new file mode 100644
index 0000000..1dbbf81
--- /dev/null
+++ b/core/java/android/content/pm/EphemeralIntentFilter.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source 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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Information about an ephemeral application intent filter.
+ * @hide
+ * @removed
+ */
+@Deprecated
+@SystemApi
+public final class EphemeralIntentFilter implements Parcelable {
+ private final InstantAppIntentFilter mInstantAppIntentFilter;
+
+ public EphemeralIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
+ mInstantAppIntentFilter = new InstantAppIntentFilter(splitName, filters);
+ }
+
+ EphemeralIntentFilter(@NonNull InstantAppIntentFilter intentFilter) {
+ mInstantAppIntentFilter = intentFilter;
+ }
+
+ EphemeralIntentFilter(Parcel in) {
+ mInstantAppIntentFilter = in.readParcelable(null /*loader*/);
+ }
+
+ public String getSplitName() {
+ return mInstantAppIntentFilter.getSplitName();
+ }
+
+ public List<IntentFilter> getFilters() {
+ return mInstantAppIntentFilter.getFilters();
+ }
+
+ /** @hide */
+ InstantAppIntentFilter getInstantAppIntentFilter() {
+ return mInstantAppIntentFilter;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mInstantAppIntentFilter, flags);
+ }
+
+ public static final Parcelable.Creator<EphemeralIntentFilter> CREATOR
+ = new Parcelable.Creator<EphemeralIntentFilter>() {
+ @Override
+ public EphemeralIntentFilter createFromParcel(Parcel in) {
+ return new EphemeralIntentFilter(in);
+ }
+ @Override
+ public EphemeralIntentFilter[] newArray(int size) {
+ return new EphemeralIntentFilter[size];
+ }
+ };
+}
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
new file mode 100644
index 0000000..12131a3
--- /dev/null
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2015 The Android Open Source 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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Information about an ephemeral application.
+ * @hide
+ * @removed
+ */
+@Deprecated
+@SystemApi
+public final class EphemeralResolveInfo implements Parcelable {
+ /** Algorithm that will be used to generate the domain digest */
+ public static final String SHA_ALGORITHM = "SHA-256";
+
+ private final InstantAppResolveInfo mInstantAppResolveInfo;
+ @Deprecated
+ private final List<IntentFilter> mLegacyFilters;
+
+ @Deprecated
+ public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName,
+ @NonNull List<IntentFilter> filters) {
+ if (uri == null || packageName == null || filters == null || filters.isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ final List<EphemeralIntentFilter> ephemeralFilters = new ArrayList<>(1);
+ ephemeralFilters.add(new EphemeralIntentFilter(packageName, filters));
+ mInstantAppResolveInfo = new InstantAppResolveInfo(uri.getHost(), packageName,
+ createInstantAppIntentFilterList(ephemeralFilters));
+ mLegacyFilters = new ArrayList<IntentFilter>(filters.size());
+ mLegacyFilters.addAll(filters);
+ }
+
+ @Deprecated
+ public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
+ @Nullable List<EphemeralIntentFilter> filters) {
+ this(digest, packageName, filters, -1 /*versionCode*/);
+ }
+
+ public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
+ @Nullable List<EphemeralIntentFilter> filters, int versionCode) {
+ mInstantAppResolveInfo = new InstantAppResolveInfo(
+ digest.getInstantAppDigest(), packageName,
+ createInstantAppIntentFilterList(filters), versionCode);
+ mLegacyFilters = null;
+ }
+
+ public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName,
+ @Nullable List<EphemeralIntentFilter> filters) {
+ this(new EphemeralDigest(hostName), packageName, filters);
+ }
+
+ EphemeralResolveInfo(Parcel in) {
+ mInstantAppResolveInfo = in.readParcelable(null /*loader*/);
+ mLegacyFilters = new ArrayList<IntentFilter>();
+ in.readList(mLegacyFilters, null /*loader*/);
+ }
+
+ /** @hide */
+ public InstantAppResolveInfo getInstantAppResolveInfo() {
+ return mInstantAppResolveInfo;
+ }
+
+ private static List<InstantAppIntentFilter> createInstantAppIntentFilterList(
+ List<EphemeralIntentFilter> filters) {
+ if (filters == null) {
+ return null;
+ }
+ final int filterCount = filters.size();
+ final List<InstantAppIntentFilter> returnList = new ArrayList<>(filterCount);
+ for (int i = 0; i < filterCount; i++) {
+ returnList.add(filters.get(i).getInstantAppIntentFilter());
+ }
+ return returnList;
+ }
+
+ public byte[] getDigestBytes() {
+ return mInstantAppResolveInfo.getDigestBytes();
+ }
+
+ public int getDigestPrefix() {
+ return mInstantAppResolveInfo.getDigestPrefix();
+ }
+
+ public String getPackageName() {
+ return mInstantAppResolveInfo.getPackageName();
+ }
+
+ public List<EphemeralIntentFilter> getIntentFilters() {
+ final List<InstantAppIntentFilter> filters = mInstantAppResolveInfo.getIntentFilters();
+ final int filterCount = filters.size();
+ final List<EphemeralIntentFilter> returnList = new ArrayList<>(filterCount);
+ for (int i = 0; i < filterCount; i++) {
+ returnList.add(new EphemeralIntentFilter(filters.get(i)));
+ }
+ return returnList;
+ }
+
+ public int getVersionCode() {
+ return mInstantAppResolveInfo.getVersionCode();
+ }
+
+ @Deprecated
+ public List<IntentFilter> getFilters() {
+ return mLegacyFilters;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mInstantAppResolveInfo, flags);
+ out.writeList(mLegacyFilters);
+ }
+
+ public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
+ = new Parcelable.Creator<EphemeralResolveInfo>() {
+ @Override
+ public EphemeralResolveInfo createFromParcel(Parcel in) {
+ return new EphemeralResolveInfo(in);
+ }
+ @Override
+ public EphemeralResolveInfo[] newArray(int size) {
+ return new EphemeralResolveInfo[size];
+ }
+ };
+
+ /**
+ * Helper class to generate and store each of the digests and prefixes
+ * sent to the Ephemeral Resolver.
+ * <p>
+ * Since intent filters may want to handle multiple hosts within a
+ * domain [eg “*.google.com”], the resolver is presented with multiple
+ * hash prefixes. For example, "a.b.c.d.e" generates digests for
+ * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e".
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class EphemeralDigest implements Parcelable {
+ private final InstantAppDigest mInstantAppDigest;
+
+ public EphemeralDigest(@NonNull String hostName) {
+ this(hostName, -1 /*maxDigests*/);
+ }
+
+ /** @hide */
+ public EphemeralDigest(@NonNull String hostName, int maxDigests) {
+ mInstantAppDigest = new InstantAppDigest(hostName, maxDigests);
+ }
+
+ EphemeralDigest(Parcel in) {
+ mInstantAppDigest = in.readParcelable(null /*loader*/);
+ }
+
+ /** @hide */
+ InstantAppDigest getInstantAppDigest() {
+ return mInstantAppDigest;
+ }
+
+ public byte[][] getDigestBytes() {
+ return mInstantAppDigest.getDigestBytes();
+ }
+
+ public int[] getDigestPrefix() {
+ return mInstantAppDigest.getDigestPrefix();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mInstantAppDigest, flags);
+ }
+
+ @SuppressWarnings("hiding")
+ public static final Parcelable.Creator<EphemeralDigest> CREATOR =
+ new Parcelable.Creator<EphemeralDigest>() {
+ @Override
+ public EphemeralDigest createFromParcel(Parcel in) {
+ return new EphemeralDigest(in);
+ }
+ @Override
+ public EphemeralDigest[] newArray(int size) {
+ return new EphemeralDigest[size];
+ }
+ };
+ }
+}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
similarity index 90%
rename from services/core/java/com/android/server/pm/InstantAppResolverConnection.java
rename to services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index a9ee411..6d6c960 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -37,29 +37,34 @@
import android.util.TimedRemoteCaller;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.TransferPipe;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeoutException;
/**
- * Represents a remote instant app resolver. It is responsible for binding to the remote
+ * Represents a remote ephemeral resolver. It is responsible for binding to the remote
* service and handling all interactions in a timely manner.
* @hide
*/
-final class InstantAppResolverConnection implements DeathRecipient {
+final class EphemeralResolverConnection implements DeathRecipient {
private static final String TAG = "PackageManager";
// This is running in a critical section and the timeout must be sufficiently low
private static final long BIND_SERVICE_TIMEOUT_MS =
Build.IS_ENG ? 500 : 300;
private static final long CALL_SERVICE_TIMEOUT_MS =
Build.IS_ENG ? 200 : 100;
- private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
private final Object mLock = new Object();
- private final GetInstantAppResolveInfoCaller mGetInstantAppResolveInfoCaller =
- new GetInstantAppResolveInfoCaller();
+ private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller =
+ new GetEphemeralResolveInfoCaller();
private final ServiceConnection mServiceConnection = new MyServiceConnection();
private final Context mContext;
/** Intent used to bind to the service */
@@ -74,7 +79,7 @@
@GuardedBy("mLock")
private IInstantAppResolver mRemoteInstance;
- public InstantAppResolverConnection(
+ public EphemeralResolverConnection(
Context context, ComponentName componentName, String action) {
mContext = context;
mIntent = new Intent(action).setComponent(componentName);
@@ -93,8 +98,8 @@
throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED);
}
try {
- return mGetInstantAppResolveInfoCaller
- .getInstantAppResolveInfoList(target, sanitizedIntent, hashPrefix, token);
+ return mGetEphemeralResolveInfoCaller
+ .getEphemeralResolveInfoList(target, sanitizedIntent, hashPrefix, token);
} catch (TimeoutException e) {
throw new ConnectionException(ConnectionException.FAILURE_CALL);
} catch (RemoteException ignore) {
@@ -166,7 +171,7 @@
if (mBindState == STATE_PENDING) {
// there is a pending bind, let's see if we can use it.
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection");
}
try {
@@ -183,7 +188,7 @@
if (mBindState == STATE_BINDING) {
// someone was binding when we called bind(), or they raced ahead while we were
// waiting in the PENDING case; wait for their result instead. Last chance!
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.i(TAG, "[" + token + "] Another thread is binding; waiting for connection");
}
waitForBindLocked(token);
@@ -201,12 +206,12 @@
IInstantAppResolver instance = null;
try {
if (doUnbind) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding");
}
mContext.unbindService(mServiceConnection);
}
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "[" + token + "] Binding to instant app resolver");
}
final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
@@ -242,7 +247,7 @@
@Override
public void binderDied() {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Binder to instant app resolver died");
}
synchronized (mLock) {
@@ -281,7 +286,7 @@
private final class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Connected to instant app resolver");
}
synchronized (mLock) {
@@ -290,7 +295,7 @@
mBindState = STATE_IDLE;
}
try {
- service.linkToDeath(InstantAppResolverConnection.this, 0 /*flags*/);
+ service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
} catch (RemoteException e) {
handleBinderDiedLocked();
}
@@ -300,7 +305,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Disconnected from instant app resolver");
}
synchronized (mLock) {
@@ -309,11 +314,11 @@
}
}
- private static final class GetInstantAppResolveInfoCaller
+ private static final class GetEphemeralResolveInfoCaller
extends TimedRemoteCaller<List<InstantAppResolveInfo>> {
private final IRemoteCallback mCallback;
- public GetInstantAppResolveInfoCaller() {
+ public GetEphemeralResolveInfoCaller() {
super(CALL_SERVICE_TIMEOUT_MS);
mCallback = new IRemoteCallback.Stub() {
@Override
@@ -328,7 +333,7 @@
};
}
- public List<InstantAppResolveInfo> getInstantAppResolveInfoList(
+ public List<InstantAppResolveInfo> getEphemeralResolveInfoList(
IInstantAppResolver target, Intent sanitizedIntent, int hashPrefix[], String token)
throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 00fdb9d..55212cc 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -51,8 +51,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.server.pm.InstantAppResolverConnection.ConnectionException;
-import com.android.server.pm.InstantAppResolverConnection.PhaseTwoCallback;
+import com.android.server.pm.EphemeralResolverConnection.ConnectionException;
+import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -66,7 +66,7 @@
/** @hide */
public abstract class InstantAppResolver {
- private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
private static final String TAG = "PackageManager";
private static final int RESOLUTION_SUCCESS = 0;
@@ -117,10 +117,10 @@
}
public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(
- InstantAppResolverConnection connection, InstantAppRequest requestObj) {
+ EphemeralResolverConnection connection, InstantAppRequest requestObj) {
final long startTime = System.currentTimeMillis();
final String token = UUID.randomUUID().toString();
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Log.d(TAG, "[" + token + "] Phase1; resolving");
}
final Intent origIntent = requestObj.origIntent;
@@ -152,7 +152,7 @@
logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token,
resolutionStatus);
}
- if (DEBUG_INSTANT && resolveInfo == null) {
+ if (DEBUG_EPHEMERAL && resolveInfo == null) {
if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) {
Log.d(TAG, "[" + token + "] Phase1; bind timed out");
} else if (resolutionStatus == RESOLUTION_CALL_TIMEOUT) {
@@ -173,11 +173,11 @@
}
public static void doInstantAppResolutionPhaseTwo(Context context,
- InstantAppResolverConnection connection, InstantAppRequest requestObj,
+ EphemeralResolverConnection connection, InstantAppRequest requestObj,
ActivityInfo instantAppInstaller, Handler callbackHandler) {
final long startTime = System.currentTimeMillis();
final String token = requestObj.responseObj.token;
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Log.d(TAG, "[" + token + "] Phase2; resolving");
}
final Intent origIntent = requestObj.origIntent;
@@ -234,7 +234,7 @@
}
logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token,
resolutionStatus);
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
if (resolutionStatus == RESOLUTION_BIND_TIMEOUT) {
Log.d(TAG, "[" + token + "] Phase2; bind timed out");
} else {
@@ -444,13 +444,13 @@
return null;
}
// No filters; we need to start phase two
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Log.d(TAG, "No app filters; go to phase 2");
}
return Collections.emptyList();
}
- final PackageManagerService.InstantAppIntentResolver instantAppResolver =
- new PackageManagerService.InstantAppIntentResolver();
+ final PackageManagerService.EphemeralIntentResolver instantAppResolver =
+ new PackageManagerService.EphemeralIntentResolver();
for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
@@ -481,11 +481,11 @@
instantAppResolver.queryIntent(
origIntent, resolvedType, false /*defaultOnly*/, userId);
if (!matchedResolveInfoList.isEmpty()) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Log.d(TAG, "[" + token + "] Found match(es); " + matchedResolveInfoList);
}
return matchedResolveInfoList;
- } else if (DEBUG_INSTANT) {
+ } else if (DEBUG_EPHEMERAL) {
Log.d(TAG, "[" + token + "] No matches found"
+ " package: " + instantAppInfo.getPackageName()
+ ", versionCode: " + instantAppInfo.getVersionCode());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a83dc7b..18c5ffd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -424,7 +424,7 @@
public static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
- private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
private static final boolean DEBUG_TRIAGED_MISSING = false;
private static final boolean DEBUG_APP_DATA = false;
@@ -981,7 +981,7 @@
private int mIntentFilterVerificationToken = 0;
/** The service connection to the ephemeral resolver */
- final InstantAppResolverConnection mInstantAppResolverConnection;
+ final EphemeralResolverConnection mInstantAppResolverConnection;
/** Component used to show resolver settings for Instant Apps */
final ComponentName mInstantAppResolverSettingsComponent;
@@ -3149,10 +3149,10 @@
final Pair<ComponentName, String> instantAppResolverComponent =
getInstantAppResolverLPr();
if (instantAppResolverComponent != null) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
}
- mInstantAppResolverConnection = new InstantAppResolverConnection(
+ mInstantAppResolverConnection = new EphemeralResolverConnection(
mContext, instantAppResolverComponent.first,
instantAppResolverComponent.second);
mInstantAppResolverSettingsComponent =
@@ -3532,7 +3532,7 @@
final String[] packageArray =
mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage);
if (packageArray.length == 0 && !Build.IS_DEBUGGABLE) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Ephemeral resolver NOT found; empty package list");
}
return null;
@@ -3547,9 +3547,19 @@
final Intent resolverIntent = new Intent(actionName);
List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
+ // temporarily look for the old action
+ if (resolvers.size() == 0) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver not found with new action; try old one");
+ }
+ actionName = Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE;
+ resolverIntent.setAction(actionName);
+ resolvers = queryIntentServicesInternal(resolverIntent, null,
+ resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
+ }
final int N = resolvers.size();
if (N == 0) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Ephemeral resolver NOT found; no matching intent filters");
}
return null;
@@ -3565,20 +3575,20 @@
final String packageName = info.serviceInfo.packageName;
if (!possiblePackages.contains(packageName) && !Build.IS_DEBUGGABLE) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Ephemeral resolver not in allowed package list;"
+ " pkg: " + packageName + ", info:" + info);
}
continue;
}
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Ephemeral resolver found;"
+ " pkg: " + packageName + ", info:" + info);
}
return new Pair<>(new ComponentName(packageName, info.serviceInfo.name), actionName);
}
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Ephemeral resolver NOT found");
}
return null;
@@ -3588,9 +3598,11 @@
String[] orderedActions = Build.IS_ENG
? new String[]{
Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE + "_TEST",
- Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE}
+ Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE,
+ Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE}
: new String[]{
- Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE};
+ Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE,
+ Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE};
final int resolveFlags =
MATCH_DIRECT_BOOT_AWARE
@@ -3606,7 +3618,7 @@
matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
resolveFlags, UserHandle.USER_SYSTEM);
if (matches.isEmpty()) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Instant App installer not found with " + action);
}
} else {
@@ -3644,6 +3656,15 @@
final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
UserHandle.USER_SYSTEM);
+ // temporarily look for the old action
+ if (matches.isEmpty()) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Ephemeral resolver settings not found with new action; try old one");
+ }
+ intent.setAction(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
+ matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+ UserHandle.USER_SYSTEM);
+ }
if (matches.isEmpty()) {
return null;
}
@@ -5986,7 +6007,7 @@
final int status = (int) (packedStatus >> 32);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS
|| status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "DENY instant app;"
+ " pkg: " + packageName + ", status: " + status);
}
@@ -5994,7 +6015,7 @@
}
}
if (ps.getInstantApp(userId)) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "DENY instant app installed;"
+ " pkg: " + packageName);
}
@@ -6630,7 +6651,7 @@
// there's a local instant application installed, but, the user has
// chosen to never use it; skip resolution and don't acknowledge
// an instant application is even available
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Instant app marked to never run; pkg: " + packageName);
}
blockResolution = true;
@@ -6638,7 +6659,7 @@
} else {
// we have a locally installed instant application; skip resolution
// but acknowledge there's an instant application available
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Found installed instant app; pkg: " + packageName);
}
localInstantApp = info;
@@ -6696,7 +6717,7 @@
// make sure this resolver is the default
ephemeralInstaller.isDefault = true;
ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
@@ -7583,7 +7604,7 @@
info.serviceInfo.splitName)) {
// requested service is defined in a split that hasn't been installed yet.
// add the installer to the resolve list
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
final ResolveInfo installerInfo = new ResolveInfo(
@@ -7705,7 +7726,7 @@
info.providerInfo.splitName)) {
// requested provider is defined in a split that hasn't been installed yet.
// add the installer to the resolve list
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
final ResolveInfo installerInfo = new ResolveInfo(
@@ -11738,14 +11759,14 @@
private void setUpInstantAppInstallerActivityLP(ActivityInfo installerActivity) {
if (installerActivity == null) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Clear ephemeral installer activity");
}
mInstantAppInstallerActivity = null;
return;
}
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.d(TAG, "Set ephemeral installer activity: "
+ installerActivity.getComponentName());
}
@@ -13205,7 +13226,7 @@
private int mFlags;
}
- static final class InstantAppIntentResolver
+ static final class EphemeralIntentResolver
extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
AuxiliaryResolveInfo.AuxiliaryFilter> {
/**
@@ -13575,7 +13596,7 @@
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
String installerPackageName, int installerUid, UserHandle user,
PackageParser.SigningDetails signingDetails) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
Slog.d(TAG, "Ephemeral install of " + packageName);
}
@@ -15059,7 +15080,7 @@
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
- if (DEBUG_INSTANT && ephemeral) {
+ if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}
@@ -15126,7 +15147,7 @@
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else if (loc == PackageHelper.RECOMMEND_INSTALL_EPHEMERAL) {
- if (DEBUG_INSTANT) {
+ if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "...setting INSTALL_EPHEMERAL install flag");
}
installFlags |= PackageManager.INSTALL_INSTANT_APP;