Merge "Change ANDROID_ID for Instant Apps" into oc-dev

am: 904e6cad28

Change-Id: Ia1f22e10846d1e6ecc2b6830c1d3156267174563
This commit is contained in:
Chad Brubaker
2017-04-19 21:34:14 +00:00
committed by android-build-merger
9 changed files with 113 additions and 0 deletions

View File

@@ -2630,4 +2630,13 @@ public class ApplicationPackageManager extends PackageManager {
throw e.rethrowAsRuntimeException();
}
}
@Override
public String getInstantAppAndroidId(String packageName, UserHandle user) {
try {
return mPM.getInstantAppAndroidId(packageName, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
}

View File

@@ -634,4 +634,6 @@ interface IPackageManager {
ComponentName getInstantAppResolverSettingsComponent();
ComponentName getInstantAppInstallerComponent();
String getInstantAppAndroidId(String packageName, int userId);
}

View File

@@ -6305,4 +6305,12 @@ public abstract class PackageManager {
*/
@SystemApi
public abstract ComponentName getInstantAppInstallerComponent();
/**
* Return the Android Id for a given Instant App.
*
* @see {@link android.provider.Settings.Secure#ANDROID_ID}
* @hide
*/
public abstract String getInstantAppAndroidId(String packageName, @NonNull UserHandle user);
}

View File

@@ -5082,6 +5082,10 @@ public final class Settings {
* (available on certain devices running Android 4.2 or higher), each user appears as a
* completely separate device, so the {@code ANDROID_ID} value is unique to each
* user.</p>
*
* <p class="note"><strong>Note:</strong> If the caller is an Instant App the id is scoped
* to the Instant App, it is generated when the Instant App is first installed and reset if
* the user clears the Instant App.
*/
public static final String ANDROID_ID = "android_id";

View File

@@ -1109,6 +1109,33 @@ public class SettingsProvider extends ContentProvider {
// Retrieve the ssaid from the table if present.
final Setting ssaid = mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId,
name);
// If the app is an Instant App use its stored SSAID instead of our own.
final String instantSsaid;
final long token = Binder.clearCallingIdentity();
try {
instantSsaid = mPackageManager.getInstantAppAndroidId(callingPkg.packageName,
owningUserId);
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to get Instant App Android ID", e);
return null;
} finally {
Binder.restoreCallingIdentity(token);
}
if (instantSsaid != null) {
// Use the stored value if it is still valid.
if (ssaid != null && instantSsaid.equals(ssaid.getValue())) {
return ssaid;
}
// The value has changed, update the stored value.
final SettingsState ssaidSettings = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_SSAID, owningUserId);
final boolean success = ssaidSettings.insertSettingLocked(name, instantSsaid, null,
true, callingPkg.packageName);
if (!success) {
throw new IllegalStateException("Failed to update instant app android id");
}
return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_SSAID, owningUserId, name);
}
// Lazy initialize ssaid if not yet present in ssaid table.
if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {

View File

@@ -35,6 +35,7 @@ import android.os.Message;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.ByteStringUtils;
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -56,8 +57,10 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Predicate;
@@ -81,6 +84,7 @@ class InstantAppRegistry {
private static final String INSTANT_APP_COOKIE_FILE_PREFIX = "cookie_";
private static final String INSTANT_APP_COOKIE_FILE_SIFFIX = ".dat";
private static final String INSTANT_APP_METADATA_FILE = "metadata.xml";
private static final String INSTANT_APP_ANDROID_ID_FILE = "android_id";
private static final String TAG_PACKAGE = "package";
private static final String TAG_PERMISSIONS = "permissions";
@@ -195,6 +199,36 @@ class InstantAppRegistry {
return null;
}
public String getInstantAppAndroidIdLPw(@NonNull String packageName,
@UserIdInt int userId) {
File idFile = new File(getInstantApplicationDir(packageName, userId),
INSTANT_APP_ANDROID_ID_FILE);
if (idFile.exists()) {
try {
return IoUtils.readFileAsString(idFile.getAbsolutePath());
} catch (IOException e) {
Slog.e(LOG_TAG, "Failed to read instant app android id file: " + idFile, e);
}
}
return generateInstantAppAndroidIdLPw(packageName, userId);
}
private String generateInstantAppAndroidIdLPw(@NonNull String packageName,
@UserIdInt int userId) {
byte[] randomBytes = new byte[8];
new SecureRandom().nextBytes(randomBytes);
String id = ByteStringUtils.toHexString(randomBytes).toLowerCase(Locale.US);
File idFile = new File(getInstantApplicationDir(packageName, userId),
INSTANT_APP_ANDROID_ID_FILE);
try (FileOutputStream fos = new FileOutputStream(idFile)) {
fos.write(id.getBytes());
} catch (IOException e) {
Slog.e(LOG_TAG, "Error writing instant app android id file: " + idFile, e);
}
return id;
}
public @Nullable List<InstantAppInfo> getInstantAppsLPr(@UserIdInt int userId) {
List<InstantAppInfo> installedApps = getInstalledInstantApplicationsLPr(userId);
List<InstantAppInfo> uninstalledApps = getUninstalledInstantApplicationsLPr(userId);
@@ -462,6 +496,7 @@ class InstantAppRegistry {
File instantAppDir = getInstantApplicationDir(packageName, userId);
new File(instantAppDir, INSTANT_APP_METADATA_FILE).delete();
new File(instantAppDir, INSTANT_APP_ICON_FILE).delete();
new File(instantAppDir, INSTANT_APP_ANDROID_ID_FILE).delete();
File cookie = peekInstantCookieFile(packageName, userId);
if (cookie != null) {
cookie.delete();

View File

@@ -23654,6 +23654,22 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
return mInstantAppInstallerActivity == null
? null : mInstantAppInstallerActivity.getComponentName();
}
@Override
public String getInstantAppAndroidId(String packageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_INSTANT_APPS,
"getInstantAppAndroidId");
enforceCrossUserPermission(Binder.getCallingUid(), userId,
true /* requireFullPermission */, false /* checkShell */,
"getInstantAppAndroidId");
// Make sure the target is an Instant App.
if (!isInstantApp(packageName, userId)) {
return null;
}
synchronized (mPackages) {
return mInstantAppRegistry.getInstantAppAndroidIdLPw(packageName, userId);
}
}
}
interface PackageSender {

View File

@@ -1134,4 +1134,11 @@ public class MockPackageManager extends PackageManager {
public ComponentName getInstantAppInstallerComponent() {
throw new UnsupportedOperationException();
}
/**
* @hide
*/
public String getInstantAppAndroidId(String packageName, UserHandle user) {
throw new UnsupportedOperationException();
}
}

View File

@@ -928,4 +928,9 @@ public class BridgePackageManager extends PackageManager {
public ComponentName getInstantAppInstallerComponent() {
return null;
}
@Override
public String getInstantAppAndroidId(String packageName, UserHandle user) {
return null;
}
}