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.content.pm.PackageInfo;
20 import android.content.pm.ShortcutInfo;
21 import android.util.Slog;
22 
23 import com.android.internal.util.Preconditions;
24 
25 import org.json.JSONException;
26 import org.json.JSONObject;
27 import org.xmlpull.v1.XmlPullParserException;
28 import org.xmlpull.v1.XmlSerializer;
29 
30 import java.io.IOException;
31 
32 /**
33  * All methods should be guarded by {@code #mShortcutUser.mService.mLock}.
34  */
35 abstract class ShortcutPackageItem {
36     private static final String TAG = ShortcutService.TAG;
37     private static final String KEY_NAME = "name";
38 
39     private final int mPackageUserId;
40     private final String mPackageName;
41 
42     private final ShortcutPackageInfo mPackageInfo;
43 
44     protected ShortcutUser mShortcutUser;
45 
ShortcutPackageItem(@onNull ShortcutUser shortcutUser, int packageUserId, @NonNull String packageName, @NonNull ShortcutPackageInfo packageInfo)46     protected ShortcutPackageItem(@NonNull ShortcutUser shortcutUser,
47             int packageUserId, @NonNull String packageName,
48             @NonNull ShortcutPackageInfo packageInfo) {
49         mShortcutUser = shortcutUser;
50         mPackageUserId = packageUserId;
51         mPackageName = Preconditions.checkStringNotEmpty(packageName);
52         mPackageInfo = Preconditions.checkNotNull(packageInfo);
53     }
54 
55     /**
56      * Change the parent {@link ShortcutUser}.  Need it in the restore code.
57      */
replaceUser(ShortcutUser user)58     public void replaceUser(ShortcutUser user) {
59         mShortcutUser = user;
60     }
61 
getUser()62     public ShortcutUser getUser() {
63         return mShortcutUser;
64     }
65 
66     /**
67      * ID of the user who actually has this package running on.  For {@link ShortcutPackage},
68      * this is the same thing as {@link #getOwnerUserId}, but if it's a {@link ShortcutLauncher} and
69      * {@link #getOwnerUserId} is of work profile, then this ID is of the primary user.
70      */
getPackageUserId()71     public int getPackageUserId() {
72         return mPackageUserId;
73     }
74 
75     /**
76      * ID of the user who sees the shortcuts from this instance.
77      */
getOwnerUserId()78     public abstract int getOwnerUserId();
79 
80     @NonNull
getPackageName()81     public String getPackageName() {
82         return mPackageName;
83     }
84 
getPackageInfo()85     public ShortcutPackageInfo getPackageInfo() {
86         return mPackageInfo;
87     }
88 
refreshPackageSignatureAndSave()89     public void refreshPackageSignatureAndSave() {
90         if (mPackageInfo.isShadow()) {
91             return; // Don't refresh for shadow user.
92         }
93         final ShortcutService s = mShortcutUser.mService;
94         mPackageInfo.refreshSignature(s, this);
95         s.scheduleSaveUser(getOwnerUserId());
96     }
97 
attemptToRestoreIfNeededAndSave()98     public void attemptToRestoreIfNeededAndSave() {
99         if (!mPackageInfo.isShadow()) {
100             return; // Already installed, nothing to do.
101         }
102         final ShortcutService s = mShortcutUser.mService;
103         if (!s.isPackageInstalled(mPackageName, mPackageUserId)) {
104             if (ShortcutService.DEBUG) {
105                 Slog.d(TAG, String.format("Package still not installed: %s/u%d",
106                         mPackageName, mPackageUserId));
107             }
108             return; // Not installed, no need to restore yet.
109         }
110         int restoreBlockReason;
111         long currentVersionCode = ShortcutInfo.VERSION_CODE_UNKNOWN;
112 
113         if (!mPackageInfo.hasSignatures()) {
114             s.wtf("Attempted to restore package " + mPackageName + "/u" + mPackageUserId
115                     + " but signatures not found in the restore data.");
116             restoreBlockReason = ShortcutInfo.DISABLED_REASON_SIGNATURE_MISMATCH;
117         } else {
118             final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
119             currentVersionCode = pi.getLongVersionCode();
120             restoreBlockReason = mPackageInfo.canRestoreTo(s, pi, canRestoreAnyVersion());
121         }
122 
123         if (ShortcutService.DEBUG) {
124             Slog.d(TAG, String.format("Restoring package: %s/u%d (version=%d) %s for u%d",
125                     mPackageName, mPackageUserId, currentVersionCode,
126                     ShortcutInfo.getDisabledReasonDebugString(restoreBlockReason),
127                     getOwnerUserId()));
128         }
129 
130         onRestored(restoreBlockReason);
131 
132         // Either way, it's no longer a shadow.
133         mPackageInfo.setShadow(false);
134 
135         s.scheduleSaveUser(mPackageUserId);
136     }
137 
canRestoreAnyVersion()138     protected abstract boolean canRestoreAnyVersion();
139 
onRestored(int restoreBlockReason)140     protected abstract void onRestored(int restoreBlockReason);
141 
saveToXml(@onNull XmlSerializer out, boolean forBackup)142     public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
143             throws IOException, XmlPullParserException;
144 
dumpCheckin(boolean clear)145     public JSONObject dumpCheckin(boolean clear) throws JSONException {
146         final JSONObject result = new JSONObject();
147         result.put(KEY_NAME, mPackageName);
148         return result;
149     }
150 
151     /**
152      * Verify various internal states.
153      */
verifyStates()154     public void verifyStates() {
155     }
156 }
157