Merge "Adjust recents onboarding logic" into pi-dev
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ee5ea80..3d169b0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2865,7 +2865,7 @@
* false if the profile has empty password as a separate challenge.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a profile owner of a managed profile.
+ * @throws SecurityException if {@code admin} is not a profile owner.
* @see UserManager#DISALLOW_UNIFIED_PASSWORD
*/
public boolean isUsingUnifiedPassword(@NonNull ComponentName admin) {
@@ -5579,10 +5579,13 @@
}
/**
- * Called by a profile owner or device owner to add a default intent handler activity for
- * intents that match a certain intent filter. This activity will remain the default intent
- * handler even if the set of potential event handlers for the intent filter changes and if the
- * intent preferences are reset.
+ * Called by a profile owner or device owner to set a default activity that the system selects
+ * to handle intents that match the given {@link IntentFilter}. This activity will remain the
+ * default intent handler even if the set of potential event handlers for the intent filter
+ * changes and if the intent preferences are reset.
+ * <p>
+ * Note that the caller should still declare the activity in the manifest, the API just sets
+ * the activity to be the default one to handle the given intent filter.
* <p>
* The default disambiguation mechanism takes over if the activity is not installed (anymore).
* When the activity is (re)installed, it is automatically reset as default intent handler for
@@ -5878,7 +5881,7 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true caller-Id information in the managed profile is not displayed.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setCrossProfileCallerIdDisabled");
@@ -5899,7 +5902,7 @@
* thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getCrossProfileCallerIdDisabled");
@@ -5939,7 +5942,7 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true contacts search in the managed profile is not displayed.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
boolean disabled) {
@@ -5961,7 +5964,7 @@
* thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getCrossProfileContactsSearchDisabled");
@@ -6032,7 +6035,7 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true, bluetooth devices cannot access enterprise contacts.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setBluetoothContactSharingDisabled");
@@ -6055,7 +6058,7 @@
* This API works on managed profile only.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getBluetoothContactSharingDisabled");
@@ -6125,7 +6128,7 @@
* {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE}.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
throwIfParentInstance("clearCrossProfileIntentFilters");
@@ -6139,21 +6142,22 @@
}
/**
- * Called by a profile or device owner to set the permitted accessibility services. When set by
+ * Called by a profile or device owner to set the permitted
+ * {@link android.accessibilityservice.AccessibilityService}. When set by
* a device owner or profile owner the restriction applies to all profiles of the user the
- * device owner or profile owner is an admin for. By default the user can use any accessiblity
- * service. When zero or more packages have been added, accessiblity services that are not in
+ * device owner or profile owner is an admin for. By default, the user can use any accessibility
+ * service. When zero or more packages have been added, accessibility services that are not in
* the list and not part of the system can not be enabled by the user.
* <p>
* Calling with a null value for the list disables the restriction so that all services can be
- * used, calling with an empty list only allows the builtin system's services.
+ * used, calling with an empty list only allows the built-in system services. Any non-system
+ * accessibility service that's currently enabled must be included in the list.
* <p>
* System accessibility services are always available to the user the list can't modify this.
- *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames List of accessibility service package names.
- * @return true if setting the restriction succeeded. It fail if there is one or more non-system
- * accessibility services enabled, that are not in the list.
+ * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
+ * contain every enabled non-system accessibility service.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
@@ -6242,10 +6246,11 @@
/**
* Called by a profile or device owner to set the permitted input methods services. When set by
* a device owner or profile owner the restriction applies to all profiles of the user the
- * device owner or profile owner is an admin for. By default the user can use any input method.
+ * device owner or profile owner is an admin for. By default, the user can use any input method.
* When zero or more packages have been added, input method that are not in the list and not
* part of the system can not be enabled by the user. This method will fail if it is called for
- * a admin that is not for the foreground user or a profile of the foreground user.
+ * a admin that is not for the foreground user or a profile of the foreground user. Any
+ * non-system input method service that's currently enabled must be included in the list.
* <p>
* Calling with a null value for the list disables the restriction so that all input methods can
* be used, calling with an empty list disables all but the system's own input methods.
@@ -6254,8 +6259,8 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames List of input method package names.
- * @return true if setting the restriction succeeded. It will fail if there are one or more
- * non-system input methods currently enabled that are not in the packageNames list.
+ * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
+ * contain every enabled non-system input method service.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean setPermittedInputMethods(
@@ -7854,11 +7859,14 @@
* {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it through the UI,
* {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission is denied and the user
* cannot manage it through the UI, and {@link #PERMISSION_GRANT_STATE_GRANTED granted} in which
- * the permission is granted and the user cannot manage it through the UI. This might affect all
- * permissions in a group that the runtime permission belongs to. This method can only be called
- * by a profile owner, device owner, or a delegate given the
+ * the permission is granted and the user cannot manage it through the UI. This method can only
+ * be called by a profile owner, device owner, or a delegate given the
* {@link #DELEGATION_PERMISSION_GRANT} scope via {@link #setDelegatedScopes}.
* <p/>
+ * Note that user cannot manage other permissions in the affected group through the UI
+ * either and their granted state will be kept as the current value. Thus, it's recommended that
+ * you set the grant state of all the permissions in the affected group.
+ * <p/>
* Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke
* the permission. It retains the previous grant, if any.
* <p/>
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 514112f..5b3d3e5 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -544,16 +544,4 @@
/** Updates the flags for the given permission. */
public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int userId);
-
- /**
- * Returns true if it's still safe to restore data backed up from this app's version
- * that was signed with restoringFromSigHash.
- */
- public abstract boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName);
-
- /**
- * Returns true if it's still safe to restore data backed up from this app's version
- * that was signed with restoringFromSig.
- */
- public abstract boolean isDataRestoreSafe(Signature restoringFromSig, String packageName);
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 375627d..da53cef 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1637,7 +1637,7 @@
<integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
<!-- Max number of connected audio devices supported by Bluetooth stack -->
- <integer name="config_bluetooth_max_connected_audio_devices">1</integer>
+ <integer name="config_bluetooth_max_connected_audio_devices">5</integer>
<!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
<bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 0d472ab..0cc7441 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -22,17 +22,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.SurfaceTexture;
-import android.media.MediaDrm;
-import android.media.MediaFormat;
-import android.media.MediaPlayer2Impl;
-import android.media.MediaPlayerBase;
-import android.media.MediaTimeProvider;
-import android.media.PlaybackParams;
-import android.media.SubtitleController;
-import android.media.SubtitleController.Anchor;
-import android.media.SubtitleData;
-import android.media.SubtitleTrack.RenderingWidget;
-import android.media.SyncParams;
import android.net.Uri;
import android.os.Handler;
import android.os.Parcel;
@@ -43,14 +32,13 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.AutoCloseable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Executor;
/**
@@ -2019,12 +2007,12 @@
public static final int MEDIA_CALL_DESELECT_TRACK = 2;
/** The player just completed a call {@code loopCurrent}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
*/
public static final int MEDIA_CALL_LOOP_CURRENT = 3;
/** The player just completed a call {@code pause}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
*/
public static final int MEDIA_CALL_PAUSE = 4;
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 50e3543..7c114df 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -35,16 +35,16 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.PowerManager;
+import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
-import android.util.ArrayMap;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.widget.VideoView;
@@ -63,10 +63,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.Runnable;
import java.lang.ref.WeakReference;
-import java.net.CookieHandler;
-import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -74,15 +71,15 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
-import java.util.Collections;
-import java.util.concurrent.Executor;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
+import java.util.concurrent.Executor;
/**
@@ -135,6 +132,14 @@
private ProvisioningThread mDrmProvisioningThread;
//--- guarded by |mDrmLock| end
+ private HandlerThread mHandlerThread;
+ private final Handler mTaskHandler;
+ private final Object mTaskLock = new Object();
+ @GuardedBy("mTaskLock")
+ private final List<Task> mPendingTasks = new LinkedList<>();
+ @GuardedBy("mTaskLock")
+ private Task mCurrentTask;
+
/**
* Default constructor.
* <p>When done with the MediaPlayer2Impl, you should call {@link #close()},
@@ -151,6 +156,11 @@
mEventHandler = null;
}
+ mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
+ mHandlerThread.start();
+ looper = mHandlerThread.getLooper();
+ mTaskHandler = new Handler(looper);
+
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
mGuard.open("close");
@@ -201,8 +211,18 @@
*/
@Override
public void play() {
- stayAwake(true);
- _start();
+ synchronized (mTaskLock) {
+ mPendingTasks.add(new Task(MEDIA_CALL_PLAY, false) {
+ @Override
+ int process() {
+ stayAwake(true);
+ _start();
+ // TODO: define public constants for return value (status).
+ return 0;
+ }
+ });
+ processPendingTask_l();
+ }
}
private native void _start() throws IllegalStateException;
@@ -218,7 +238,21 @@
* @throws IllegalStateException if it is called in an invalid state
*/
@Override
- public native void prepare();
+ public void prepare() {
+ synchronized (mTaskLock) {
+ mPendingTasks.add(new Task(MEDIA_CALL_PREPARE, true) {
+ @Override
+ int process() {
+ _prepare();
+ // TODO: define public constants for return value (status).
+ return 0;
+ }
+ });
+ processPendingTask_l();
+ }
+ }
+
+ public native void _prepare();
/**
* Pauses playback. Call play() to resume.
@@ -695,6 +729,18 @@
public void clearPendingCommands() {
}
+ @GuardedBy("mTaskLock")
+ private void processPendingTask_l() {
+ if (mCurrentTask != null) {
+ return;
+ }
+ if (!mPendingTasks.isEmpty()) {
+ Task task = mPendingTasks.remove(0);
+ mCurrentTask = task;
+ mTaskHandler.post(task);
+ }
+ }
+
private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
throws IOException {
Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
@@ -2525,6 +2571,10 @@
synchronized (mEventCbLock) {
mEventCallbackRecords.clear();
}
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ mHandlerThread = null;
+ }
if (mTimeProvider != null) {
mTimeProvider.close();
mTimeProvider = null;
@@ -2638,6 +2688,13 @@
}
}
}
+ synchronized (mTaskLock) {
+ if (mCurrentTask.mMediaCallType == MEDIA_CALL_PREPARE
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
return;
}
@@ -4506,4 +4563,38 @@
}
}
}
+
+ private abstract class Task implements Runnable {
+ private final int mMediaCallType;
+ private final boolean mNeedToWaitForEventToComplete;
+
+ public Task (int mediaCallType, boolean needToWaitForEventToComplete) {
+ mMediaCallType = mediaCallType;
+ mNeedToWaitForEventToComplete = needToWaitForEventToComplete;
+ }
+
+ abstract int process();
+
+ @Override
+ public void run() {
+ int status = process();
+
+ if (!mNeedToWaitForEventToComplete) {
+ final DataSourceDesc dsd;
+ synchronized (mSrcLock) {
+ dsd = mCurrentDSD;
+ }
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onCallComplete(
+ MediaPlayer2Impl.this, dsd, mMediaCallType, status));
+ }
+ }
+ synchronized (mTaskLock) {
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
+ }
+ };
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index a647dcc..32a00d5 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -292,7 +292,9 @@
mCloseGuard.close();
if (mClosed.compareAndSet(false, true)) {
mMediaScanner.close();
- mMediaProvider.close();
+ if (mMediaProvider != null) {
+ mMediaProvider.close();
+ }
native_finalize();
}
}
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index af78777..918b82b 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -1490,7 +1490,7 @@
{"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface},
{"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
{"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
- {"prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
+ {"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
{"_start", "()V", (void *)android_media_MediaPlayer2_start},
{"_stop", "()V", (void *)android_media_MediaPlayer2_stop},
{"native_getMediaPlayer2State", "()I", (void *)android_media_MediaPlayer2_getMediaPlayer2State},
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 4443130..3cf374f 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -23,7 +23,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
@@ -31,7 +30,6 @@
import android.os.ParcelFileDescriptor;
import android.util.Slog;
-import com.android.server.LocalServices;
import com.android.server.backup.utils.AppBackupUtils;
import java.io.BufferedInputStream;
@@ -237,7 +235,7 @@
if (home != null) {
try {
homeInfo = mPackageManager.getPackageInfo(home.getPackageName(),
- PackageManager.GET_SIGNING_CERTIFICATES);
+ PackageManager.GET_SIGNATURES);
homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
homeVersion = homeInfo.getLongVersionCode();
homeSigHashes = BackupUtils.hashSignatureArray(homeInfo.signatures);
@@ -254,11 +252,10 @@
// 2. the home app [or absence] we now use differs from the prior state,
// OR 3. it looks like we use the same home app + version as before, but
// the signatures don't match so we treat them as different apps.
- PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
|| !Objects.equals(home, mStoredHomeComponent)
|| (home != null
- && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo, pmi));
+ && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo));
if (needHomeBackup) {
if (DEBUG) {
Slog.i(TAG, "Home preference changed; backing up new state " + home);
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index c1a1c1d..0ca4f25 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -36,13 +36,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.LocalServices;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.KeyValueAdbRestoreEngine;
@@ -209,11 +207,8 @@
if (info.path.equals(BACKUP_MANIFEST_FILENAME)) {
Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
info);
- PackageManagerInternal pmi = LocalServices.getService(
- PackageManagerInternal.class);
RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
- mBackupManagerService.getPackageManager(), allowApks, info, signatures,
- pmi);
+ mBackupManagerService.getPackageManager(), allowApks, info, signatures);
mManifestSignatures.put(info.packageName, signatures);
mPackagePolicies.put(pkg, restorePolicy);
mPackageInstallers.put(pkg, info.installerPackageName);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index dacde0b..e576b3c 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -40,7 +40,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -48,7 +47,6 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.LocalServices;
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.KeyValueAdbRestoreEngine;
@@ -472,11 +470,9 @@
if (info.path.equals(BACKUP_MANIFEST_FILENAME)) {
Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
info);
- PackageManagerInternal pmi = LocalServices.getService(
- PackageManagerInternal.class);
RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
mBackupManagerService.getPackageManager(), allowApks,
- info, signatures, pmi);
+ info, signatures);
mManifestSignatures.put(info.packageName, signatures);
mPackagePolicies.put(pkg, restorePolicy);
mPackageInstallers.put(pkg, info.installerPackageName);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 4b467e5..3caa1e7 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -43,7 +43,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Message;
@@ -58,7 +57,6 @@
import com.android.internal.backup.IBackupTransport;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
-import com.android.server.LocalServices;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.BackupUtils;
import com.android.server.backup.PackageManagerBackupAgent;
@@ -506,7 +504,7 @@
try {
mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo(
- pkgName, PackageManager.GET_SIGNING_CERTIFICATES);
+ pkgName, PackageManager.GET_SIGNATURES);
} catch (NameNotFoundException e) {
// Whoops, we thought we could restore this package but it
// turns out not to be present. Skip it.
@@ -621,8 +619,7 @@
}
Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
- PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
- if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage, pmi)) {
+ if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
Slog.w(TAG, "Signature mismatch restoring " + packageName);
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 90c1387..6780563 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -25,7 +25,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Process;
import android.util.Slog;
@@ -38,9 +37,6 @@
* Utility methods wrapping operations on ApplicationInfo and PackageInfo.
*/
public class AppBackupUtils {
-
- private static final boolean DEBUG = false;
-
/**
* Returns whether app is eligible for backup.
*
@@ -92,8 +88,7 @@
public static boolean appIsRunningAndEligibleForBackupWithTransport(
@Nullable TransportClient transportClient, String packageName, PackageManager pm) {
try {
- PackageInfo packageInfo = pm.getPackageInfo(packageName,
- PackageManager.GET_SIGNING_CERTIFICATES);
+ PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
ApplicationInfo applicationInfo = packageInfo.applicationInfo;
if (!appIsEligibleForBackup(applicationInfo, pm)
|| appIsStopped(applicationInfo)
@@ -170,18 +165,12 @@
*
* <ul>
* <li>Source and target have at least one signature each
- * <li>Target contains all signatures in source, and nothing more
+ * <li>Target contains all signatures in source
* </ul>
*
- * or if both source and target have exactly one signature, and they don't match, we check
- * if the app was ever signed with source signature (i.e. app has rotated key)
- * Note: key rotation is only supported for apps ever signed with one key, and those apps will
- * not be allowed to be signed by more certificates in the future
- *
* Note that if {@param target} is null we return false.
*/
- public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target,
- PackageManagerInternal pmi) {
+ public static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
if (target == null) {
return false;
}
@@ -198,52 +187,33 @@
return true;
}
+ Signature[] deviceSigs = target.signatures;
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs);
+ }
+
// Don't allow unsigned apps on either end
- if (ArrayUtils.isEmpty(storedSigs)) {
+ if (ArrayUtils.isEmpty(storedSigs) || ArrayUtils.isEmpty(deviceSigs)) {
return false;
}
- Signature[][] deviceHistorySigs = target.signingCertificateHistory;
- if (ArrayUtils.isEmpty(deviceHistorySigs)) {
- Slog.w(TAG, "signingCertificateHistory is empty, app was either unsigned or the flag" +
- " PackageManager#GET_SIGNING_CERTIFICATES was not specified");
- return false;
- }
+ // Signatures can be added over time, so the target-device apk needs to contain all the
+ // source-device apk signatures, but not necessarily the other way around.
+ int nStored = storedSigs.length;
+ int nDevice = deviceSigs.length;
- if (DEBUG) {
- Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceHistorySigs);
- }
-
- final int nStored = storedSigs.length;
- if (nStored == 1) {
- // if the app is only signed with one sig, it's possible it has rotated its key
- // (the checks with signing history are delegated to PackageManager)
- // TODO: address the case that app has declared restoreAnyVersion and is restoring
- // from higher version to lower after having rotated the key (i.e. higher version has
- // different sig than lower version that we want to restore to)
- return pmi.isDataRestoreSafe(storedSigs[0], target.packageName);
- } else {
- // the app couldn't have rotated keys, since it was signed with multiple sigs - do
- // a comprehensive 1-to-1 signatures check
- // since app hasn't rotated key, we only need to check with deviceHistorySigs[0]
- Signature[] deviceSigs = deviceHistorySigs[0];
- int nDevice = deviceSigs.length;
-
- // ensure that each stored sig matches an on-device sig
- for (int i = 0; i < nStored; i++) {
- boolean match = false;
- for (int j = 0; j < nDevice; j++) {
- if (storedSigs[i].equals(deviceSigs[j])) {
- match = true;
- break;
- }
- }
- if (!match) {
- return false;
+ for (int i = 0; i < nStored; i++) {
+ boolean match = false;
+ for (int j = 0; j < nDevice; j++) {
+ if (storedSigs[i].equals(deviceSigs[j])) {
+ match = true;
+ break;
}
}
- // we have found a match for all stored sigs
- return true;
+ if (!match) {
+ return false;
+ }
}
+ return true;
}
}
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index df7e6d4..10f0695 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -30,7 +30,6 @@
import android.content.pm.PackageInstaller.Session;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Bundle;
import android.os.IBinder;
@@ -38,7 +37,6 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.server.LocalServices;
import com.android.server.backup.FileMetadata;
import com.android.server.backup.restore.RestoreDeleteObserver;
import com.android.server.backup.restore.RestorePolicy;
@@ -144,8 +142,9 @@
uninstall = true;
} else {
try {
- PackageInfo pkg = packageManager.getPackageInfo(info.packageName,
- PackageManager.GET_SIGNING_CERTIFICATES);
+ PackageInfo pkg = packageManager.getPackageInfo(
+ info.packageName,
+ PackageManager.GET_SIGNATURES);
if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP)
== 0) {
Slog.w(TAG, "Restore stream contains apk of package "
@@ -155,9 +154,7 @@
} else {
// So far so good -- do the signatures match the manifest?
Signature[] sigs = manifestSignatures.get(info.packageName);
- PackageManagerInternal pmi = LocalServices.getService(
- PackageManagerInternal.class);
- if (AppBackupUtils.signaturesMatch(sigs, pkg, pmi)) {
+ if (AppBackupUtils.signaturesMatch(sigs, pkg)) {
// If this is a system-uid app without a declared backup agent,
// don't restore any of the file data.
if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 6dd5284..cc26ff8 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -50,7 +50,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Bundle;
import android.os.Process;
@@ -386,8 +385,7 @@
* @return a restore policy constant.
*/
public RestorePolicy chooseRestorePolicy(PackageManager packageManager,
- boolean allowApks, FileMetadata info, Signature[] signatures,
- PackageManagerInternal pmi) {
+ boolean allowApks, FileMetadata info, Signature[] signatures) {
if (signatures == null) {
return RestorePolicy.IGNORE;
}
@@ -397,7 +395,7 @@
// Okay, got the manifest info we need...
try {
PackageInfo pkgInfo = packageManager.getPackageInfo(
- info.packageName, PackageManager.GET_SIGNING_CERTIFICATES);
+ info.packageName, PackageManager.GET_SIGNATURES);
// Fall through to IGNORE if the app explicitly disallows backup
final int flags = pkgInfo.applicationInfo.flags;
if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
@@ -413,7 +411,7 @@
// such packages are signed with the platform cert instead of
// the app developer's cert, so they're different on every
// device.
- if (AppBackupUtils.signaturesMatch(signatures, pkgInfo, pmi)) {
+ if (AppBackupUtils.signaturesMatch(signatures, pkgInfo)) {
if ((pkgInfo.applicationInfo.flags
& ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
Slog.i(TAG, "Package has restoreAnyVersion; taking data");
diff --git a/services/core/java/com/android/server/backup/BackupUtils.java b/services/core/java/com/android/server/backup/BackupUtils.java
index f44afe4..e5d564d 100644
--- a/services/core/java/com/android/server/backup/BackupUtils.java
+++ b/services/core/java/com/android/server/backup/BackupUtils.java
@@ -18,12 +18,9 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.util.Slog;
-import com.android.internal.util.ArrayUtils;
-
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@@ -33,10 +30,9 @@
public class BackupUtils {
private static final String TAG = "BackupUtils";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = false; // STOPSHIP if true
- public static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target,
- PackageManagerInternal pmi) {
+ public static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target) {
if (target == null) {
return false;
}
@@ -51,54 +47,48 @@
return true;
}
- // Don't allow unsigned apps on either end
- if (ArrayUtils.isEmpty(storedSigHashes)) {
- return false;
- }
-
- Signature[][] deviceHistorySigs = target.signingCertificateHistory;
- if (ArrayUtils.isEmpty(deviceHistorySigs)) {
- Slog.w(TAG, "signingCertificateHistory is empty, app was either unsigned or the flag" +
- " PackageManager#GET_SIGNING_CERTIFICATES was not specified");
- return false;
- }
-
- if (DEBUG) {
- Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
- + " device=" + deviceHistorySigs);
- }
-
- final int nStored = storedSigHashes.size();
- if (nStored == 1) {
- // if the app is only signed with one sig, it's possible it has rotated its key
- // the checks with signing history are delegated to PackageManager
- // TODO: address the case that app has declared restoreAnyVersion and is restoring
- // from higher version to lower after having rotated the key (i.e. higher version has
- // different sig than lower version that we want to restore to)
- return pmi.isDataRestoreSafe(storedSigHashes.get(0), target.packageName);
- } else {
- // the app couldn't have rotated keys, since it was signed with multiple sigs - do
- // a comprehensive 1-to-1 signatures check
- // since app hasn't rotated key, we only need to check with deviceHistorySigs[0]
- ArrayList<byte[]> deviceHashes = hashSignatureArray(deviceHistorySigs[0]);
- int nDevice = deviceHashes.size();
-
- // ensure that each stored sig matches an on-device sig
- for (int i = 0; i < nStored; i++) {
- boolean match = false;
- for (int j = 0; j < nDevice; j++) {
- if (Arrays.equals(storedSigHashes.get(i), deviceHashes.get(j))) {
- match = true;
- break;
- }
- }
- if (!match) {
- return false;
- }
- }
- // we have found a match for all stored sigs
+ // Allow unsigned apps, but not signed on one device and unsigned on the other
+ // !!! TODO: is this the right policy?
+ Signature[] deviceSigs = target.signatures;
+ if (DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
+ + " device=" + deviceSigs);
+ if ((storedSigHashes == null || storedSigHashes.size() == 0)
+ && (deviceSigs == null || deviceSigs.length == 0)) {
return true;
}
+ if (storedSigHashes == null || deviceSigs == null) {
+ return false;
+ }
+
+ // !!! TODO: this demands that every stored signature match one
+ // that is present on device, and does not demand the converse.
+ // Is this this right policy?
+ final int nStored = storedSigHashes.size();
+ final int nDevice = deviceSigs.length;
+
+ // hash each on-device signature
+ ArrayList<byte[]> deviceHashes = new ArrayList<byte[]>(nDevice);
+ for (int i = 0; i < nDevice; i++) {
+ deviceHashes.add(hashSignature(deviceSigs[i]));
+ }
+
+ // now ensure that each stored sig (hash) matches an on-device sig (hash)
+ for (int n = 0; n < nStored; n++) {
+ boolean match = false;
+ final byte[] storedHash = storedSigHashes.get(n);
+ for (int i = 0; i < nDevice; i++) {
+ if (Arrays.equals(storedHash, deviceHashes.get(i))) {
+ match = true;
+ break;
+ }
+ }
+ // match is false when no on-device sig matched one of the stored ones
+ if (!match) {
+ return false;
+ }
+ }
+
+ return true;
}
public static byte[] hashSignature(byte[] signature) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6513683..0da7b01 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -176,7 +176,6 @@
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser.ParseFlags;
import android.content.pm.PackageParser.ServiceIntentInfo;
-import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.PackageStats;
import android.content.pm.PackageUserState;
@@ -23329,39 +23328,6 @@
}
@Override
- public boolean isDataRestoreSafe(byte[] restoringFromSigHash, String packageName) {
- SigningDetails sd = getSigningDetails(packageName);
- if (sd == null) {
- return false;
- }
- return sd.hasSha256Certificate(restoringFromSigHash,
- SigningDetails.CertCapabilities.INSTALLED_DATA);
- }
-
- @Override
- public boolean isDataRestoreSafe(Signature restoringFromSig, String packageName) {
- SigningDetails sd = getSigningDetails(packageName);
- if (sd == null) {
- return false;
- }
- return sd.hasCertificate(restoringFromSig,
- SigningDetails.CertCapabilities.INSTALLED_DATA);
- }
-
- private SigningDetails getSigningDetails(String packageName) {
- synchronized (mPackages) {
- if (packageName == null) {
- return null;
- }
- PackageParser.Package p = mPackages.get(packageName);
- if (p == null) {
- return null;
- }
- return p.mSigningDetails;
- }
- }
-
- @Override
public int getPermissionFlagsTEMP(String permName, String packageName, int userId) {
return PackageManagerService.this.getPermissionFlags(permName, packageName, userId);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 44dd924..520ed25 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -18,12 +18,10 @@
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ShortcutInfo;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.LocalServices;
import com.android.server.backup.BackupUtils;
import libcore.util.HexEncoding;
@@ -139,8 +137,7 @@
//@DisabledReason
public int canRestoreTo(ShortcutService s, PackageInfo currentPackage, boolean anyVersionOkay) {
- PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
- if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage, pmi)) {
+ if (!BackupUtils.signaturesMatch(mSigHashes, currentPackage)) {
Slog.w(TAG, "Can't restore: Package signature mismatch");
return ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 70fb616..8c35188 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3125,8 +3125,7 @@
try {
return mIPackageManager.getPackageInfo(
packageName, PACKAGE_MATCH_FLAGS
- | (getSignatures ? PackageManager.GET_SIGNING_CERTIFICATES : 0),
- userId);
+ | (getSignatures ? PackageManager.GET_SIGNATURES : 0), userId);
} catch (RemoteException e) {
// Shouldn't happen.
Slog.wtf(TAG, "RemoteException", e);
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
index 8ccacb8..86c83d6 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -18,14 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Process;
import android.platform.test.annotations.Presubmit;
@@ -35,7 +30,6 @@
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.testutils.PackageManagerStub;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,14 +45,7 @@
private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
- private PackageManagerStub mPackageManagerStub;
- private PackageManagerInternal mMockPackageManagerInternal;
-
- @Before
- public void setUp() throws Exception {
- mPackageManagerStub = new PackageManagerStub();
- mMockPackageManagerInternal = mock(PackageManagerInternal.class);
- }
+ private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
@Test
public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception {
@@ -371,8 +358,7 @@
@Test
public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null);
assertThat(result).isFalse();
}
@@ -383,8 +369,7 @@
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isTrue();
}
@@ -393,11 +378,10 @@
public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+ packageInfo.signatures = new Signature[] {SIGNATURE_1};
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
assertThat(result).isFalse();
}
@@ -406,11 +390,10 @@
public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
+ packageInfo.signatures = new Signature[] {SIGNATURE_1};
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isFalse();
}
@@ -421,11 +404,11 @@
signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[0][0];
+ packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
+ packageInfo);
assertThat(result).isFalse();
}
@@ -435,11 +418,11 @@
signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = null;
+ packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1},
+ packageInfo);
assertThat(result).isFalse();
}
@@ -448,11 +431,10 @@
public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = null;
+ packageInfo.signatures = null;
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(null, packageInfo);
assertThat(result).isFalse();
}
@@ -461,11 +443,10 @@
public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
throws Exception {
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[0][0];
+ packageInfo.signatures = new Signature[0];
packageInfo.applicationInfo = new ApplicationInfo();
- boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
- mMockPackageManagerInternal);
+ boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo);
assertThat(result).isFalse();
}
@@ -477,14 +458,11 @@
Signature signature3Copy = new Signature(SIGNATURE_3.toByteArray());
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
+ packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
- new Signature[] {signature3Copy, signature1Copy, signature2Copy}, packageInfo,
- mMockPackageManagerInternal);
+ new Signature[]{signature3Copy, signature1Copy, signature2Copy}, packageInfo);
assertThat(result).isTrue();
}
@@ -495,14 +473,11 @@
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
+ packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
- new Signature[]{signature2Copy, signature1Copy}, packageInfo,
- mMockPackageManagerInternal);
+ new Signature[]{signature2Copy, signature1Copy}, packageInfo);
assertThat(result).isTrue();
}
@@ -513,14 +488,11 @@
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {signature1Copy, signature2Copy}
- };
+ packageInfo.signatures = new Signature[]{signature1Copy, signature2Copy};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
- new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo,
- mMockPackageManagerInternal);
+ new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo);
assertThat(result).isFalse();
}
@@ -531,76 +503,11 @@
Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
+ packageInfo.signatures = new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3};
packageInfo.applicationInfo = new ApplicationInfo();
boolean result = AppBackupUtils.signaturesMatch(
- new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_singleStoredSignatureNoRotation_returnsTrue()
- throws Exception {
- Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
-
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
- packageInfo.packageName);
-
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
- packageInfo, mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void signaturesMatch_singleStoredSignatureWithRotationAssumeDataCapability_returnsTrue()
- throws Exception {
- Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
-
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- // we know signature1Copy is in history, and we want to assume it has
- // SigningDetails.CertCapabilities.INSTALLED_DATA capability
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
- packageInfo.packageName);
-
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
- packageInfo, mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void
- signaturesMatch_singleStoredSignatureWithRotationAssumeNoDataCapability_returnsFalse()
- throws Exception {
- Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
-
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- // we know signature1Copy is in history, but we want to assume it does not have
- // SigningDetails.CertCapabilities.INSTALLED_DATA capability
- doReturn(false).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
- packageInfo.packageName);
-
- boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
- packageInfo, mMockPackageManagerInternal);
+ new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo);
assertThat(result).isFalse();
}
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 5f052ce..0cdf04b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -28,9 +28,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -40,7 +37,6 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.Bundle;
import android.os.Process;
@@ -83,7 +79,6 @@
@Mock private BytesReadListener mBytesReadListenerMock;
@Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
- @Mock private PackageManagerInternal mMockPackageManagerInternal;
private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
private Context mContext;
@@ -144,8 +139,7 @@
Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
fileMetadata);
RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
- mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
- mMockPackageManagerInternal);
+ mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -158,8 +152,7 @@
signatures = tarBackupReader.readAppManifestAndReturnSignatures(
fileMetadata);
restorePolicy = tarBackupReader.chooseRestorePolicy(
- mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
- mMockPackageManagerInternal);
+ mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
@@ -221,8 +214,7 @@
mBytesReadListenerMock, mBackupManagerMonitorMock);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- true /* allowApks */, new FileMetadata(), null /* signatures */,
- mMockPackageManagerInternal);
+ true /* allowApks */, new FileMetadata(), null /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
verifyZeroInteractions(mBackupManagerMonitorMock);
@@ -242,8 +234,7 @@
PackageManagerStub.sPackageInfo = null;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- true /* allowApks */, info, new Signature[0] /* signatures */,
- mMockPackageManagerInternal);
+ true /* allowApks */, info, new Signature[0] /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -267,8 +258,7 @@
PackageManagerStub.sPackageInfo = null;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- true /* allowApks */, info, new Signature[0] /* signatures */,
- mMockPackageManagerInternal);
+ true /* allowApks */, info, new Signature[0] /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -293,8 +283,7 @@
PackageManagerStub.sPackageInfo = null;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
- mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -318,8 +307,7 @@
PackageManagerStub.sPackageInfo = packageInfo;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
- mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -345,8 +333,7 @@
PackageManagerStub.sPackageInfo = packageInfo;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
- mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -371,11 +358,11 @@
packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
packageInfo.applicationInfo.backupAgentName = null;
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_2}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_2};
PackageManagerStub.sPackageInfo = packageInfo;
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), signatures);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -396,19 +383,16 @@
Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |=
ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
packageInfo.applicationInfo.backupAgentName = "backup.agent";
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
PackageManagerStub.sPackageInfo = packageInfo;
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
- packageInfo.packageName);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), signatures);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -428,19 +412,16 @@
Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |=
ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
packageInfo.applicationInfo.backupAgentName = null;
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
PackageManagerStub.sPackageInfo = packageInfo;
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
- packageInfo.packageName);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
+ false /* allowApks */, new FileMetadata(), signatures);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -463,20 +444,17 @@
info.version = 1;
PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
packageInfo.applicationInfo.backupAgentName = null;
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
packageInfo.versionCode = 2;
PackageManagerStub.sPackageInfo = packageInfo;
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
- packageInfo.packageName);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, info, signatures, mMockPackageManagerInternal);
+ false /* allowApks */, info, signatures);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -501,20 +479,17 @@
info.hasApk = true;
PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
packageInfo.applicationInfo.backupAgentName = null;
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
packageInfo.versionCode = 1;
PackageManagerStub.sPackageInfo = packageInfo;
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
- packageInfo.packageName);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- true /* allowApks */, info, signatures, mMockPackageManagerInternal);
+ true /* allowApks */, info, signatures);
assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
verifyNoMoreInteractions(mBackupManagerMonitorMock);
@@ -535,20 +510,17 @@
info.version = 2;
PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
packageInfo.applicationInfo.backupAgentName = null;
- packageInfo.signingCertificateHistory = new Signature[][] {{FAKE_SIGNATURE_1}};
+ packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
packageInfo.versionCode = 1;
PackageManagerStub.sPackageInfo = packageInfo;
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
- packageInfo.packageName);
RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
- false /* allowApks */, info, signatures, mMockPackageManagerInternal);
+ false /* allowApks */, info, signatures);
assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
diff --git a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
index a0cefbf..c016e61 100644
--- a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
@@ -15,298 +15,73 @@
*/
package com.android.server.pm.backup;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser.Package;
import android.content.pm.Signature;
+import android.test.AndroidTestCase;
import android.test.MoreAsserts;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.backup.BackupUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import java.util.ArrayList;
import java.util.Arrays;
@SmallTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class BackupUtilsTest {
+public class BackupUtilsTest extends AndroidTestCase {
- private static final Signature SIGNATURE_1 = generateSignature((byte) 1);
- private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
- private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
- private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
- private static final byte[] SIGNATURE_HASH_1 = BackupUtils.hashSignature(SIGNATURE_1);
- private static final byte[] SIGNATURE_HASH_2 = BackupUtils.hashSignature(SIGNATURE_2);
- private static final byte[] SIGNATURE_HASH_3 = BackupUtils.hashSignature(SIGNATURE_3);
- private static final byte[] SIGNATURE_HASH_4 = BackupUtils.hashSignature(SIGNATURE_4);
-
- private PackageManagerInternal mMockPackageManagerInternal;
-
- @Before
- public void setUp() throws Exception {
- mMockPackageManagerInternal = mock(PackageManagerInternal.class);
+ private Signature[] genSignatures(String... signatures) {
+ final Signature[] sigs = new Signature[signatures.length];
+ for (int i = 0; i < signatures.length; i++){
+ sigs[i] = new Signature(signatures[i].getBytes());
+ }
+ return sigs;
}
- @Test
- public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, null,
- mMockPackageManagerInternal);
+ private PackageInfo genPackage(String... signatures) {
+ final PackageInfo pi = new PackageInfo();
+ pi.packageName = "package";
+ pi.applicationInfo = new ApplicationInfo();
+ pi.signatures = genSignatures(signatures);
- assertThat(result).isFalse();
+ return pi;
}
- @Test
- public void signaturesMatch_systemApplication_returnsTrue() throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.applicationInfo = new ApplicationInfo();
- packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ public void testSignaturesMatch() {
+ final ArrayList<byte[]> stored1 = BackupUtils.hashSignatureArray(Arrays.asList(
+ "abc".getBytes()));
+ final ArrayList<byte[]> stored2 = BackupUtils.hashSignatureArray(Arrays.asList(
+ "abc".getBytes(), "def".getBytes()));
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
+ PackageInfo pi;
- assertThat(result).isTrue();
+ // False for null package.
+ assertFalse(BackupUtils.signaturesMatch(stored1, null));
+
+ // If it's a system app, signatures don't matter.
+ pi = genPackage("xyz");
+ pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ assertTrue(BackupUtils.signaturesMatch(stored1, pi));
+
+ // Non system apps.
+ assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc")));
+
+ // Superset is okay.
+ assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc", "xyz")));
+ assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "abc")));
+
+ assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz")));
+ assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "def")));
+
+ assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("def", "abc")));
+ assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("x", "def", "abc", "y")));
+
+ // Subset is not okay.
+ assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("abc")));
+ assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("def")));
}
- @Test
- public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- boolean result = BackupUtils.signaturesMatch(null, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
-
- @Test
- public void
- signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[0][0];
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void
- signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = null;
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = null;
- packageInfo.applicationInfo = new ApplicationInfo();
-
- boolean result = BackupUtils.signaturesMatch(null, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[0][0];
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_equalSignatures_returnsTrue() throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- storedSigHashes.add(SIGNATURE_HASH_2);
- storedSigHashes.add(SIGNATURE_HASH_3);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- storedSigHashes.add(SIGNATURE_HASH_2);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1, SIGNATURE_2}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- storedSigHashes.add(SIGNATURE_HASH_2);
- storedSigHashes.add(SIGNATURE_HASH_3);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.signingCertificateHistory = new Signature[][] {
- {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}
- };
- packageInfo.applicationInfo = new ApplicationInfo();
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- storedSigHashes.add(SIGNATURE_HASH_2);
- storedSigHashes.add(SIGNATURE_HASH_4);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void signaturesMatch_singleStoredSignatureNoRotation_returnsTrue()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
- packageInfo.packageName);
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void signaturesMatch_singleStoredSignatureWithRotationAssumeDataCapability_returnsTrue()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- // we know SIGNATURE_1 is in history, and we want to assume it has
- // SigningDetails.CertCapabilities.INSTALLED_DATA capability
- doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
- packageInfo.packageName);
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void
- signaturesMatch_singleStoredSignatureWithRotationAssumeNoDataCapability_returnsFalse()
- throws Exception {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = "test";
- packageInfo.signingCertificateHistory = new Signature[][] {{SIGNATURE_1}, {SIGNATURE_2}};
- packageInfo.applicationInfo = new ApplicationInfo();
-
- // we know SIGNATURE_1 is in history, but we want to assume it does not have
- // SigningDetails.CertCapabilities.INSTALLED_DATA capability
- doReturn(false).when(mMockPackageManagerInternal).isDataRestoreSafe(SIGNATURE_HASH_1,
- packageInfo.packageName);
-
- ArrayList<byte[]> storedSigHashes = new ArrayList<>();
- storedSigHashes.add(SIGNATURE_HASH_1);
- boolean result = BackupUtils.signaturesMatch(storedSigHashes, packageInfo,
- mMockPackageManagerInternal);
-
- assertThat(result).isFalse();
- }
-
- @Test
public void testHashSignature() {
final byte[] sig1 = "abc".getBytes();
final byte[] sig2 = "def".getBytes();
@@ -340,10 +115,4 @@
MoreAsserts.assertEquals(hash2a, listA.get(1));
MoreAsserts.assertEquals(hash2a, listB.get(1));
}
-
- private static Signature generateSignature(byte i) {
- byte[] signatureBytes = new byte[256];
- signatureBytes[0] = i;
- return new Signature(signatureBytes);
- }
}