OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / pm / ShortcutPackageInfo.java
1 /*
2  * Copyright (C) 2016 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 package com.android.server.pm;
17
18 import android.annotation.NonNull;
19 import android.annotation.UserIdInt;
20 import android.content.pm.PackageInfo;
21 import android.util.Slog;
22
23 import com.android.server.backup.BackupUtils;
24
25 import libcore.io.Base64;
26 import libcore.util.HexEncoding;
27
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30 import org.xmlpull.v1.XmlSerializer;
31
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.util.ArrayList;
35
36 /**
37  * Package information used by {@link android.content.pm.ShortcutManager} for backup / restore.
38  *
39  * All methods should be guarded by {@code ShortcutService.mLock}.
40  */
41 class ShortcutPackageInfo {
42     private static final String TAG = ShortcutService.TAG;
43
44     static final String TAG_ROOT = "package-info";
45     private static final String ATTR_VERSION = "version";
46     private static final String ATTR_LAST_UPDATE_TIME = "last_udpate_time";
47     private static final String ATTR_SHADOW = "shadow";
48
49     private static final String TAG_SIGNATURE = "signature";
50     private static final String ATTR_SIGNATURE_HASH = "hash";
51
52     private static final int VERSION_UNKNOWN = -1;
53
54     /**
55      * When true, this package information was restored from the previous device, and the app hasn't
56      * been installed yet.
57      */
58     private boolean mIsShadow;
59     private int mVersionCode = VERSION_UNKNOWN;
60     private long mLastUpdateTime;
61     private ArrayList<byte[]> mSigHashes;
62
63     private ShortcutPackageInfo(int versionCode, long lastUpdateTime,
64             ArrayList<byte[]> sigHashes, boolean isShadow) {
65         mVersionCode = versionCode;
66         mLastUpdateTime = lastUpdateTime;
67         mIsShadow = isShadow;
68         mSigHashes = sigHashes;
69     }
70
71     public static ShortcutPackageInfo newEmpty() {
72         return new ShortcutPackageInfo(VERSION_UNKNOWN, /* last update time =*/ 0,
73                 new ArrayList<>(0), /* isShadow */ false);
74     }
75
76     public boolean isShadow() {
77         return mIsShadow;
78     }
79
80     public void setShadow(boolean shadow) {
81         mIsShadow = shadow;
82     }
83
84     public int getVersionCode() {
85         return mVersionCode;
86     }
87
88     public long getLastUpdateTime() {
89         return mLastUpdateTime;
90     }
91
92     public void updateVersionInfo(@NonNull PackageInfo pi) {
93         if (pi != null) {
94             mVersionCode = pi.versionCode;
95             mLastUpdateTime = pi.lastUpdateTime;
96         }
97     }
98
99     public boolean hasSignatures() {
100         return mSigHashes.size() > 0;
101     }
102
103     public boolean canRestoreTo(ShortcutService s, PackageInfo target) {
104         if (!s.shouldBackupApp(target)) {
105             // "allowBackup" was true when backed up, but now false.
106             Slog.w(TAG, "Can't restore: package no longer allows backup");
107             return false;
108         }
109         if (target.versionCode < mVersionCode) {
110             Slog.w(TAG, String.format(
111                     "Can't restore: package current version %d < backed up version %d",
112                     target.versionCode, mVersionCode));
113             return false;
114         }
115         if (!BackupUtils.signaturesMatch(mSigHashes, target)) {
116             Slog.w(TAG, "Can't restore: Package signature mismatch");
117             return false;
118         }
119         return true;
120     }
121
122     public static ShortcutPackageInfo generateForInstalledPackage(
123             ShortcutService s, String packageName, @UserIdInt int packageUserId) {
124         final PackageInfo pi = s.getPackageInfoWithSignatures(packageName, packageUserId);
125         if (pi.signatures == null || pi.signatures.length == 0) {
126             Slog.e(TAG, "Can't get signatures: package=" + packageName);
127             return null;
128         }
129         final ShortcutPackageInfo ret = new ShortcutPackageInfo(pi.versionCode, pi.lastUpdateTime,
130                 BackupUtils.hashSignatureArray(pi.signatures), /* shadow=*/ false);
131
132         return ret;
133     }
134
135     public void refresh(ShortcutService s, ShortcutPackageItem pkg) {
136         if (mIsShadow) {
137             s.wtf("Attempted to refresh package info for shadow package " + pkg.getPackageName()
138                     + ", user=" + pkg.getOwnerUserId());
139             return;
140         }
141         // Note use mUserId here, rather than userId.
142         final PackageInfo pi = s.getPackageInfoWithSignatures(
143                 pkg.getPackageName(), pkg.getPackageUserId());
144         if (pi == null) {
145             Slog.w(TAG, "Package not found: " + pkg.getPackageName());
146             return;
147         }
148         mVersionCode = pi.versionCode;
149         mLastUpdateTime = pi.lastUpdateTime;
150         mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
151     }
152
153     public void saveToXml(XmlSerializer out) throws IOException {
154
155         out.startTag(null, TAG_ROOT);
156
157         ShortcutService.writeAttr(out, ATTR_VERSION, mVersionCode);
158         ShortcutService.writeAttr(out, ATTR_LAST_UPDATE_TIME, mLastUpdateTime);
159         ShortcutService.writeAttr(out, ATTR_SHADOW, mIsShadow);
160
161         for (int i = 0; i < mSigHashes.size(); i++) {
162             out.startTag(null, TAG_SIGNATURE);
163             ShortcutService.writeAttr(out, ATTR_SIGNATURE_HASH, Base64.encode(mSigHashes.get(i)));
164             out.endTag(null, TAG_SIGNATURE);
165         }
166         out.endTag(null, TAG_ROOT);
167     }
168
169     public void loadFromXml(XmlPullParser parser, boolean fromBackup)
170             throws IOException, XmlPullParserException {
171
172         final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
173
174         final long lastUpdateTime = ShortcutService.parseLongAttribute(
175                 parser, ATTR_LAST_UPDATE_TIME);
176
177         // When restoring from backup, it's always shadow.
178         final boolean shadow =
179                 fromBackup || ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
180
181         final ArrayList<byte[]> hashes = new ArrayList<>();
182
183         final int outerDepth = parser.getDepth();
184         int type;
185         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
186                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
187             if (type != XmlPullParser.START_TAG) {
188                 continue;
189             }
190             final int depth = parser.getDepth();
191             final String tag = parser.getName();
192
193             if (depth == outerDepth + 1) {
194                 switch (tag) {
195                     case TAG_SIGNATURE: {
196                         final String hash = ShortcutService.parseStringAttribute(
197                                 parser, ATTR_SIGNATURE_HASH);
198                         hashes.add(Base64.decode(hash.getBytes()));
199                         continue;
200                     }
201                 }
202             }
203             ShortcutService.warnForInvalidTag(depth, tag);
204         }
205
206         // Successfully loaded; replace the feilds.
207         mVersionCode = versionCode;
208         mLastUpdateTime = lastUpdateTime;
209         mIsShadow = shadow;
210         mSigHashes = hashes;
211     }
212
213     public void dump(PrintWriter pw, String prefix) {
214         pw.println();
215
216         pw.print(prefix);
217         pw.println("PackageInfo:");
218
219         pw.print(prefix);
220         pw.print("  IsShadow: ");
221         pw.print(mIsShadow);
222         pw.println();
223
224         pw.print(prefix);
225         pw.print("  Version: ");
226         pw.print(mVersionCode);
227         pw.println();
228
229         pw.print(prefix);
230         pw.print("  Last package update time: ");
231         pw.print(mLastUpdateTime);
232         pw.println();
233
234         for (int i = 0; i < mSigHashes.size(); i++) {
235             pw.print(prefix);
236             pw.print("    ");
237             pw.print("SigHash: ");
238             pw.println(HexEncoding.encode(mSigHashes.get(i)));
239         }
240     }
241 }