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