Add API to track package changes

After any package install, removal or update, save the changed
package and update a global sequence number. At any point, apps
can query for the packages changed since a particular sequence
number.

If a package is changed multiple times, it is only included once
in the change list.

Bug: 33865505
Test: Create sample app to query for changes and see which packages are changed after performing certain operations
Change-Id: Ia4646035362b16a97110e05f3f909ce385b48428
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0c6c4ba..333e412 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -29,6 +29,7 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
@@ -506,6 +507,15 @@
     }
 
     @Override
+    public ChangedPackages getChangedPackages(int sequenceNumber) {
+        try {
+            return mPM.getChangedPackages(sequenceNumber, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     @SuppressWarnings("unchecked")
     public FeatureInfo[] getSystemAvailableFeatures() {
         try {
diff --git a/core/java/android/content/pm/ChangedPackages.aidl b/core/java/android/content/pm/ChangedPackages.aidl
new file mode 100644
index 0000000..1a9f5a1
--- /dev/null
+++ b/core/java/android/content/pm/ChangedPackages.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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;
+
+parcelable ChangedPackages;
\ No newline at end of file
diff --git a/core/java/android/content/pm/ChangedPackages.java b/core/java/android/content/pm/ChangedPackages.java
new file mode 100644
index 0000000..94b8a5d
--- /dev/null
+++ b/core/java/android/content/pm/ChangedPackages.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2017, 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.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * Packages that have been changed since the last time they
+ * were requested.
+ */
+public final class ChangedPackages implements Parcelable {
+    /** The last known sequence number for these changes */
+    private final int mSequenceNumber;
+    /** The names of the packages that have changed */
+    private final List<String> mPackageNames;
+
+    public ChangedPackages(int sequenceNumber, @NonNull List<String> packageNames) {
+        this.mSequenceNumber = sequenceNumber;
+        this.mPackageNames = packageNames;
+    }
+
+    /** @hide */
+    protected ChangedPackages(Parcel in) {
+        mSequenceNumber = in.readInt();
+        mPackageNames = in.createStringArrayList();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSequenceNumber);
+        dest.writeStringList(mPackageNames);
+    }
+
+    /**
+     * Returns the last known sequence number for these changes.
+     */
+    public int getSequenceNumber() {
+        return mSequenceNumber;
+    }
+
+    /**
+     * Returns the names of the packages that have changed.
+     */
+    public @NonNull List<String> getPackageNames() {
+        return mPackageNames;
+    }
+
+    public static final Parcelable.Creator<ChangedPackages> CREATOR =
+            new Parcelable.Creator<ChangedPackages>() {
+        public ChangedPackages createFromParcel(Parcel in) {
+            return new ChangedPackages(in);
+        }
+
+        public ChangedPackages[] newArray(int size) {
+            return new ChangedPackages[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 3fb46cf..9d36a73 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -23,6 +23,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
+import android.content.pm.ChangedPackages;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageInstallObserver2;
@@ -611,6 +612,8 @@
     String getServicesSystemSharedLibraryPackageName();
     String getSharedSystemSharedLibraryPackageName();
 
+    ChangedPackages getChangedPackages(int sequenceNumber, int userId);
+
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
 
     List<String> getPreviousCodePaths(in String packageName);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b20b5e2..308153d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -20,6 +20,7 @@
 import android.annotation.CheckResult;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -3853,6 +3854,17 @@
     public abstract @NonNull String getSharedSystemSharedLibraryPackageName();
 
     /**
+     * Returns the names of the packages that have been changed
+     * [eg. added, removed or updated] since the given sequence
+     * number.
+     * <p>If no packages have been changed, returns <code>null</code>.
+     * <p>The sequence number starts at <code>0</code> and is
+     * reset every boot.
+     */
+    public abstract @Nullable ChangedPackages getChangedPackages(
+            @IntRange(from=0) int sequenceNumber);
+
+    /**
      * Get a list of features that are available on the
      * system.
      *