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 final 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     public ShortcutUser getUser() {
     55         return mShortcutUser;
     56     }
     57 
     58     /**
     59      * ID of the user who actually has this package running on.  For {@link ShortcutPackage},
     60      * this is the same thing as {@link #getOwnerUserId}, but if it's a {@link ShortcutLauncher} and
     61      * {@link #getOwnerUserId} is of a work profile, then this ID could be the user who owns the
     62      * profile.
     63      */
     64     public int getPackageUserId() {
     65         return mPackageUserId;
     66     }
     67 
     68     /**
     69      * ID of the user who sees the shortcuts from this instance.
     70      */
     71     public abstract int getOwnerUserId();
     72 
     73     @NonNull
     74     public String getPackageName() {
     75         return mPackageName;
     76     }
     77 
     78     public ShortcutPackageInfo getPackageInfo() {
     79         return mPackageInfo;
     80     }
     81 
     82     public void refreshPackageInfoAndSave() {
     83         if (mPackageInfo.isShadow()) {
     84             return; // Don't refresh for shadow user.
     85         }
     86         final ShortcutService s = mShortcutUser.mService;
     87         mPackageInfo.refresh(s, this);
     88         s.scheduleSaveUser(getOwnerUserId());
     89     }
     90 
     91     public void attemptToRestoreIfNeededAndSave() {
     92         if (!mPackageInfo.isShadow()) {
     93             return; // Already installed, nothing to do.
     94         }
     95         final ShortcutService s = mShortcutUser.mService;
     96         if (!s.isPackageInstalled(mPackageName, mPackageUserId)) {
     97             if (ShortcutService.DEBUG) {
     98                 Slog.d(TAG, String.format("Package still not installed: %s user=%d",
     99                         mPackageName, mPackageUserId));
    100             }
    101             return; // Not installed, no need to restore yet.
    102         }
    103         if (!mPackageInfo.hasSignatures()) {
    104             s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
    105                     + " but signatures not found in the restore data.");
    106             onRestoreBlocked();
    107             return;
    108         }
    109 
    110         final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
    111         if (!mPackageInfo.canRestoreTo(s, pi)) {
    112             // Package is now installed, but can't restore.  Let the subclass do the cleanup.
    113             onRestoreBlocked();
    114             return;
    115         }
    116         if (ShortcutService.DEBUG) {
    117             Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
    118                     mPackageUserId, getOwnerUserId()));
    119         }
    120 
    121         onRestored();
    122 
    123         // Now the package is not shadow.
    124         mPackageInfo.setShadow(false);
    125 
    126         s.scheduleSaveUser(mPackageUserId);
    127     }
    128 
    129     /**
    130      * Called when the new package can't be restored because it has a lower version number
    131      * or different signatures.
    132      */
    133     protected abstract void onRestoreBlocked();
    134 
    135     /**
    136      * Called when the new package is successfully restored.
    137      */
    138     protected abstract void onRestored();
    139 
    140     public abstract void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
    141             throws IOException, XmlPullParserException;
    142 
    143     public JSONObject dumpCheckin(boolean clear) throws JSONException {
    144         final JSONObject result = new JSONObject();
    145         result.put(KEY_NAME, mPackageName);
    146         return result;
    147     }
    148 
    149     /**
    150      * Verify various internal states.
    151      */
    152     public void verifyStates() {
    153     }
    154 }
    155