1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.rollback;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.annotation.TestApi;
22 import android.content.pm.VersionedPackage;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.util.IntArray;
26 import android.util.SparseLongArray;
27 
28 import java.util.ArrayList;
29 
30 /**
31  * Information about a rollback available for a particular package.
32  *
33  * @hide
34  */
35 @SystemApi @TestApi
36 public final class PackageRollbackInfo implements Parcelable {
37 
38     private final VersionedPackage mVersionRolledBackFrom;
39     private final VersionedPackage mVersionRolledBackTo;
40 
41     /**
42      * Encapsulates information required to restore a snapshot of an app's userdata.
43      *
44      * @hide
45      */
46     public static class RestoreInfo {
47         public final int userId;
48         public final int appId;
49         public final String seInfo;
50 
RestoreInfo(int userId, int appId, String seInfo)51         public RestoreInfo(int userId, int appId, String seInfo) {
52             this.userId = userId;
53             this.appId = appId;
54             this.seInfo = seInfo;
55         }
56     }
57 
58     /*
59      * The list of users for which we need to backup userdata for this package. Backups of
60      * credential encrypted data are listed as pending if the user hasn't unlocked their device
61      * with credentials yet.
62      */
63     // NOTE: Not a part of the Parcelable representation of this object.
64     private final IntArray mPendingBackups;
65 
66     /**
67      * The list of users for which we need to restore userdata for this package. This field is
68      * non-null only after a rollback for this package has been committed.
69      */
70     // NOTE: Not a part of the Parcelable representation of this object.
71     private final ArrayList<RestoreInfo> mPendingRestores;
72 
73     /**
74      * Whether this instance represents the PackageRollbackInfo for an APEX module.
75      */
76     private final boolean mIsApex;
77 
78     /*
79      * The list of users for which snapshots have been saved.
80      */
81     // NOTE: Not a part of the Parcelable representation of this object.
82     private final IntArray mSnapshottedUsers;
83 
84     /**
85      * A mapping between user and an inode of theirs CE data snapshot.
86      */
87     // NOTE: Not a part of the Parcelable representation of this object.
88     private final SparseLongArray mCeSnapshotInodes;
89 
90     /**
91      * Returns the name of the package to roll back from.
92      */
93     @NonNull
getPackageName()94     public String getPackageName() {
95         return mVersionRolledBackFrom.getPackageName();
96     }
97 
98     /**
99      * Returns the version of the package rolled back from.
100      */
101     @NonNull
getVersionRolledBackFrom()102     public VersionedPackage getVersionRolledBackFrom() {
103         return mVersionRolledBackFrom;
104     }
105 
106     /**
107      * Returns the version of the package rolled back to.
108      */
109     @NonNull
getVersionRolledBackTo()110     public VersionedPackage getVersionRolledBackTo() {
111         return mVersionRolledBackTo;
112     }
113 
114     /** @hide */
addPendingBackup(int userId)115     public void addPendingBackup(int userId) {
116         mPendingBackups.add(userId);
117     }
118 
119     /** @hide */
getPendingBackups()120     public IntArray getPendingBackups() {
121         return mPendingBackups;
122     }
123 
124     /** @hide */
getPendingRestores()125     public ArrayList<RestoreInfo> getPendingRestores() {
126         return mPendingRestores;
127     }
128 
129     /** @hide */
getRestoreInfo(int userId)130     public RestoreInfo getRestoreInfo(int userId) {
131         for (RestoreInfo ri : mPendingRestores) {
132             if (ri.userId == userId) {
133                 return ri;
134             }
135         }
136 
137         return null;
138     }
139 
140     /** @hide */
removeRestoreInfo(RestoreInfo ri)141     public void removeRestoreInfo(RestoreInfo ri) {
142         mPendingRestores.remove(ri);
143     }
144 
145     /** @hide */
isApex()146     public boolean isApex() {
147         return mIsApex;
148     }
149 
150     /** @hide */
getSnapshottedUsers()151     public IntArray getSnapshottedUsers() {
152         return mSnapshottedUsers;
153     }
154 
155     /** @hide */
getCeSnapshotInodes()156     public SparseLongArray getCeSnapshotInodes() {
157         return mCeSnapshotInodes;
158     }
159 
160     /** @hide */
putCeSnapshotInode(int userId, long ceSnapshotInode)161     public void putCeSnapshotInode(int userId, long ceSnapshotInode) {
162         mCeSnapshotInodes.put(userId, ceSnapshotInode);
163     }
164 
165     /** @hide */
removePendingBackup(int userId)166     public void removePendingBackup(int userId) {
167         int idx = mPendingBackups.indexOf(userId);
168         if (idx != -1) {
169             mPendingBackups.remove(idx);
170         }
171     }
172 
173     /** @hide */
removePendingRestoreInfo(int userId)174     public void removePendingRestoreInfo(int userId) {
175         removeRestoreInfo(getRestoreInfo(userId));
176     }
177 
178     /** @hide */
PackageRollbackInfo(VersionedPackage packageRolledBackFrom, VersionedPackage packageRolledBackTo, @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores, boolean isApex, @NonNull IntArray snapshottedUsers, @NonNull SparseLongArray ceSnapshotInodes)179     public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
180             VersionedPackage packageRolledBackTo,
181             @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
182             boolean isApex, @NonNull IntArray snapshottedUsers,
183             @NonNull SparseLongArray ceSnapshotInodes) {
184         this.mVersionRolledBackFrom = packageRolledBackFrom;
185         this.mVersionRolledBackTo = packageRolledBackTo;
186         this.mPendingBackups = pendingBackups;
187         this.mPendingRestores = pendingRestores;
188         this.mIsApex = isApex;
189         this.mSnapshottedUsers = snapshottedUsers;
190         this.mCeSnapshotInodes = ceSnapshotInodes;
191     }
192 
PackageRollbackInfo(Parcel in)193     private PackageRollbackInfo(Parcel in) {
194         this.mVersionRolledBackFrom = VersionedPackage.CREATOR.createFromParcel(in);
195         this.mVersionRolledBackTo = VersionedPackage.CREATOR.createFromParcel(in);
196         this.mIsApex = in.readBoolean();
197         this.mPendingRestores = null;
198         this.mPendingBackups = null;
199         this.mSnapshottedUsers = null;
200         this.mCeSnapshotInodes = null;
201     }
202 
203     @Override
describeContents()204     public int describeContents() {
205         return 0;
206     }
207 
208     @Override
writeToParcel(Parcel out, int flags)209     public void writeToParcel(Parcel out, int flags) {
210         mVersionRolledBackFrom.writeToParcel(out, flags);
211         mVersionRolledBackTo.writeToParcel(out, flags);
212         out.writeBoolean(mIsApex);
213     }
214 
215     public static final @NonNull Parcelable.Creator<PackageRollbackInfo> CREATOR =
216             new Parcelable.Creator<PackageRollbackInfo>() {
217         public PackageRollbackInfo createFromParcel(Parcel in) {
218             return new PackageRollbackInfo(in);
219         }
220 
221         public PackageRollbackInfo[] newArray(int size) {
222             return new PackageRollbackInfo[size];
223         }
224     };
225 }
226